OSDN Git Service

[Refactor] #37353 メッセージ整理。 / Refactor messages.
[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         ARTIFACT_IDX i;
5237         ARTIFACT_IDX k;
5238         POSITION x, y;
5239         int n = 0;
5240         ARTIFACT_IDX z;
5241         u16b why = 3;
5242         ARTIFACT_IDX *who;
5243         FILE *fff;
5244         GAME_TEXT file_name[1024];
5245         GAME_TEXT base_name[MAX_NLEN];
5246
5247         bool *okay;
5248
5249         /* Open a new file */
5250         fff = my_fopen_temp(file_name, 1024);
5251
5252         if (!fff) {
5253             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5254             msg_print(NULL);
5255             return;
5256         }
5257
5258         /* Allocate the "who" array */
5259         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
5260
5261         /* Allocate the "okay" array */
5262         C_MAKE(okay, max_a_idx, bool);
5263
5264         /* Scan the artifacts */
5265         for (k = 0; k < max_a_idx; k++)
5266         {
5267                 artifact_type *a_ptr = &a_info[k];
5268
5269                 /* Default */
5270                 okay[k] = FALSE;
5271
5272                 /* Skip "empty" artifacts */
5273                 if (!a_ptr->name) continue;
5274
5275                 /* Skip "uncreated" artifacts */
5276                 if (!a_ptr->cur_num) continue;
5277
5278                 /* Assume okay */
5279                 okay[k] = TRUE;
5280         }
5281
5282         /* Check the dungeon */
5283         for (y = 0; y < cur_hgt; y++)
5284         {
5285                 for (x = 0; x < cur_wid; x++)
5286                 {
5287                         cave_type *c_ptr = &cave[y][x];
5288
5289                         OBJECT_IDX this_o_idx, next_o_idx = 0;
5290
5291                         /* Scan all objects in the grid */
5292                         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
5293                         {
5294                                 object_type *o_ptr;
5295                                 o_ptr = &o_list[this_o_idx];
5296
5297                                 /* Acquire next object */
5298                                 next_o_idx = o_ptr->next_o_idx;
5299
5300                                 /* Ignore non-artifacts */
5301                                 if (!object_is_fixed_artifact(o_ptr)) continue;
5302
5303                                 /* Ignore known items */
5304                                 if (object_is_known(o_ptr)) continue;
5305
5306                                 /* Note the artifact */
5307                                 okay[o_ptr->name1] = FALSE;
5308                         }
5309                 }
5310         }
5311
5312         /* Check the inventory and equipment */
5313         for (i = 0; i < INVEN_TOTAL; i++)
5314         {
5315                 object_type *o_ptr = &inventory[i];
5316
5317                 /* Ignore non-objects */
5318                 if (!o_ptr->k_idx) continue;
5319
5320                 /* Ignore non-artifacts */
5321                 if (!object_is_fixed_artifact(o_ptr)) continue;
5322
5323                 /* Ignore known items */
5324                 if (object_is_known(o_ptr)) continue;
5325
5326                 /* Note the artifact */
5327                 okay[o_ptr->name1] = FALSE;
5328         }
5329
5330         for (k = 0; k < max_a_idx; k++)
5331         {
5332                 if (okay[k]) who[n++] = k;
5333         }
5334
5335         /* Select the sort method */
5336         ang_sort_comp = ang_sort_art_comp;
5337         ang_sort_swap = ang_sort_art_swap;
5338
5339         /* Sort the array by dungeon depth of monsters */
5340         ang_sort(who, &why, n);
5341
5342         /* Scan the artifacts */
5343         for (k = 0; k < n; k++)
5344         {
5345                 artifact_type *a_ptr = &a_info[who[k]];
5346
5347                 /* Paranoia */
5348                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
5349
5350                 /* Obtain the base object type */
5351                 z = lookup_kind(a_ptr->tval, a_ptr->sval);
5352
5353                 /* Real object */
5354                 if (z)
5355                 {
5356                         object_type forge;
5357                         object_type *q_ptr;
5358                         q_ptr = &forge;
5359
5360                         /* Create fake object */
5361                         object_prep(q_ptr, z);
5362
5363                         /* Make it an artifact */
5364                         q_ptr->name1 = (byte)who[k];
5365
5366                         /* Display as if known */
5367                         q_ptr->ident |= IDENT_STORE;
5368
5369                         /* Describe the artifact */
5370                         object_desc(base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
5371                 }
5372
5373                 /* Hack -- Build the artifact name */
5374                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
5375         }
5376
5377         /* Free the "who" array */
5378         C_KILL(who, max_a_idx, ARTIFACT_IDX);
5379
5380         /* Free the "okay" array */
5381         C_KILL(okay, max_a_idx, bool);
5382         my_fclose(fff);
5383
5384         /* Display the file contents */
5385         show_file(TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
5386
5387         /* Remove the file */
5388         fd_kill(file_name);
5389 }
5390
5391
5392 /*
5393  * Display known uniques
5394  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
5395  */
5396 static void do_cmd_knowledge_uniques(void)
5397 {
5398         IDX i;
5399         int k, n = 0;
5400         u16b why = 2;
5401         IDX *who;
5402
5403         FILE *fff;
5404
5405         GAME_TEXT file_name[1024];
5406
5407         int n_alive[10];
5408         int n_alive_surface = 0;
5409         int n_alive_over100 = 0;
5410         int n_alive_total = 0;
5411         int max_lev = -1;
5412
5413         for (i = 0; i < 10; i++) n_alive[i] = 0;
5414
5415         /* Open a new file */
5416         fff = my_fopen_temp(file_name, 1024);
5417
5418         if (!fff)
5419         {
5420                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5421                 msg_print(NULL);
5422                 return;
5423         }
5424
5425         /* Allocate the "who" array */
5426         C_MAKE(who, max_r_idx, s16b);
5427
5428         /* Scan the monsters */
5429         for (i = 1; i < max_r_idx; i++)
5430         {
5431                 monster_race *r_ptr = &r_info[i];
5432                 int          lev;
5433
5434                 if (!r_ptr->name) continue;
5435
5436                 /* Require unique monsters */
5437                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
5438
5439                 /* Only display "known" uniques */
5440                 if (!cheat_know && !r_ptr->r_sights) continue;
5441
5442                 /* Only print rarity <= 100 uniques */
5443                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
5444
5445                 /* Only "alive" uniques */
5446                 if (r_ptr->max_num == 0) continue;
5447
5448                 if (r_ptr->level)
5449                 {
5450                         lev = (r_ptr->level - 1) / 10;
5451                         if (lev < 10)
5452                         {
5453                                 n_alive[lev]++;
5454                                 if (max_lev < lev) max_lev = lev;
5455                         }
5456                         else n_alive_over100++;
5457                 }
5458                 else n_alive_surface++;
5459
5460                 /* Collect "appropriate" monsters */
5461                 who[n++] = i;
5462         }
5463
5464         /* Select the sort method */
5465         ang_sort_comp = ang_sort_comp_hook;
5466         ang_sort_swap = ang_sort_swap_hook;
5467
5468         /* Sort the array by dungeon depth of monsters */
5469         ang_sort(who, &why, n);
5470
5471         if (n_alive_surface)
5472         {
5473                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
5474                 n_alive_total += n_alive_surface;
5475         }
5476         for (i = 0; i <= max_lev; i++)
5477         {
5478                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
5479                 n_alive_total += n_alive[i];
5480         }
5481         if (n_alive_over100)
5482         {
5483                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
5484                 n_alive_total += n_alive_over100;
5485         }
5486
5487         if (n_alive_total)
5488         {
5489                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
5490                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
5491         }
5492         else
5493         {
5494                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
5495         }
5496
5497         /* Scan the monster races */
5498         for (k = 0; k < n; k++)
5499         {
5500                 monster_race *r_ptr = &r_info[who[k]];
5501
5502                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
5503         }
5504
5505         /* Free the "who" array */
5506         C_KILL(who, max_r_idx, s16b);
5507         my_fclose(fff);
5508
5509         /* Display the file contents */
5510         show_file(TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
5511
5512         /* Remove the file */
5513         fd_kill(file_name);
5514 }
5515
5516
5517 /*
5518  * Display weapon-exp
5519  */
5520 static void do_cmd_knowledge_weapon_exp(void)
5521 {
5522         int i, num, weapon_exp;
5523         KIND_OBJECT_IDX j;
5524
5525         FILE *fff;
5526
5527         GAME_TEXT file_name[1024];
5528         char tmp[30];
5529
5530         /* Open a new file */
5531         fff = my_fopen_temp(file_name, 1024);
5532         if (!fff) {
5533             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5534             msg_print(NULL);
5535             return;
5536         }
5537
5538         for (i = 0; i < 5; i++)
5539         {
5540                 for (num = 0; num < 64; num++)
5541                 {
5542                         for (j = 0; j < max_k_idx; j++)
5543                         {
5544                                 object_kind *k_ptr = &k_info[j];
5545
5546                                 if ((k_ptr->tval == TV_SWORD - i) && (k_ptr->sval == num))
5547                                 {
5548                                         if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
5549
5550                                         weapon_exp = p_ptr->weapon_exp[4 - i][num];
5551                                         strip_name(tmp, j);
5552                                         fprintf(fff, "%-25s ", tmp);
5553                                         if (weapon_exp >= s_info[p_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
5554                                         else fprintf(fff, " ");
5555                                         fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
5556                                         if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
5557                                         fprintf(fff, "\n");
5558                                         break;
5559                                 }
5560                         }
5561                 }
5562         }
5563         my_fclose(fff);
5564
5565         /* Display the file contents */
5566         show_file(TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
5567
5568         /* Remove the file */
5569         fd_kill(file_name);
5570 }
5571
5572
5573 /*!
5574  * @brief 魔法の経験値を表示するコマンドのメインルーチン
5575  * Display spell-exp
5576  * @return なし
5577  */
5578 static void do_cmd_knowledge_spell_exp(void)
5579 {
5580         SPELL_IDX i = 0;
5581         int spell_exp, exp_level;
5582
5583         FILE *fff;
5584         const magic_type *s_ptr;
5585
5586         GAME_TEXT file_name[1024];
5587
5588         /* Open a new file */
5589         fff = my_fopen_temp(file_name, 1024);
5590         if (!fff) {
5591             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5592             msg_print(NULL);
5593             return;
5594         }
5595
5596         if (p_ptr->realm1 != REALM_NONE)
5597         {
5598                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[p_ptr->realm1]);
5599                 for (i = 0; i < 32; i++)
5600                 {
5601                         if (!is_magic(p_ptr->realm1))
5602                         {
5603                                 s_ptr = &technic_info[p_ptr->realm1 - MIN_TECHNIC][i];
5604                         }
5605                         else
5606                         {
5607                                 s_ptr = &mp_ptr->info[p_ptr->realm1 - 1][i];
5608                         }
5609                         if (s_ptr->slevel >= 99) continue;
5610                         spell_exp = p_ptr->spell_exp[i];
5611                         exp_level = spell_exp_level(spell_exp);
5612                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm1, i, SPELL_NAME));
5613                         if (p_ptr->realm1 == REALM_HISSATSU)
5614                                 fprintf(fff, "[--]");
5615                         else
5616                         {
5617                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
5618                                 else fprintf(fff, " ");
5619                                 fprintf(fff, "%s", exp_level_str[exp_level]);
5620                         }
5621                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5622                         fprintf(fff, "\n");
5623                 }
5624         }
5625
5626         if (p_ptr->realm2 != REALM_NONE)
5627         {
5628                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[p_ptr->realm2]);
5629                 for (i = 0; i < 32; i++)
5630                 {
5631                         if (!is_magic(p_ptr->realm1))
5632                         {
5633                                 s_ptr = &technic_info[p_ptr->realm2 - MIN_TECHNIC][i];
5634                         }
5635                         else
5636                         {
5637                                 s_ptr = &mp_ptr->info[p_ptr->realm2 - 1][i];
5638                         }
5639                         if (s_ptr->slevel >= 99) continue;
5640
5641                         spell_exp = p_ptr->spell_exp[i + 32];
5642                         exp_level = spell_exp_level(spell_exp);
5643                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm2, i, SPELL_NAME));
5644                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
5645                         else fprintf(fff, " ");
5646                         fprintf(fff, "%s", exp_level_str[exp_level]);
5647                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5648                         fprintf(fff, "\n");
5649                 }
5650         }
5651         my_fclose(fff);
5652
5653         /* Display the file contents */
5654         show_file(TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
5655
5656         /* Remove the file */
5657         fd_kill(file_name);
5658 }
5659
5660
5661 /*!
5662  * @brief スキル情報を表示するコマンドのメインルーチン /
5663  * Display skill-exp
5664  * @return なし
5665  */
5666 static void do_cmd_knowledge_skill_exp(void)
5667 {
5668         int i = 0, skill_exp;
5669
5670         FILE *fff;
5671
5672         GAME_TEXT file_name[1024];
5673         GAME_TEXT skill_name[3][20]={_("マーシャルアーツ", "Martial Arts    "),
5674                                                         _("二刀流          ", "Dual Wielding   "), 
5675                                                         _("乗馬            ", "Riding          ")};
5676
5677         /* Open a new file */
5678         fff = my_fopen_temp(file_name, 1024);
5679         if (!fff) {
5680             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5681             msg_print(NULL);
5682             return;
5683         }
5684
5685         for (i = 0; i < 3; i++)
5686         {
5687                 skill_exp = p_ptr->skill_exp[i];
5688                 fprintf(fff, "%-20s ", skill_name[i]);
5689                 if (skill_exp >= s_info[p_ptr->pclass].s_max[i]) fprintf(fff, "!");
5690                 else fprintf(fff, " ");
5691                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
5692                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
5693                 fprintf(fff, "\n");
5694         }
5695         my_fclose(fff);
5696
5697         /* Display the file contents */
5698         show_file(TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
5699
5700         /* Remove the file */
5701         fd_kill(file_name);
5702 }
5703
5704
5705 /*!
5706  * @brief 英単語、句、説を複数形を変換する / Pluralize a monster name
5707  * @param Name 変換したい文字列の参照ポインタ
5708  * @return なし
5709  */
5710 void plural_aux(char *Name)
5711 {
5712         int NameLen = strlen(Name);
5713
5714         if (my_strstr(Name, "Disembodied hand"))
5715         {
5716                 strcpy(Name, "Disembodied hands that strangled people");
5717         }
5718         else if (my_strstr(Name, "Colour out of space"))
5719         {
5720                 strcpy(Name, "Colours out of space");
5721         }
5722         else if (my_strstr(Name, "stairway to hell"))
5723         {
5724                 strcpy(Name, "stairways to hell");
5725         }
5726         else if (my_strstr(Name, "Dweller on the threshold"))
5727         {
5728                 strcpy(Name, "Dwellers on the threshold");
5729         }
5730         else if (my_strstr(Name, " of "))
5731         {
5732                 cptr aider = my_strstr(Name, " of ");
5733                 char dummy[80];
5734                 int i = 0;
5735                 cptr ctr = Name;
5736
5737                 while (ctr < aider)
5738                 {
5739                         dummy[i] = *ctr;
5740                         ctr++; i++;
5741                 }
5742
5743                 if (dummy[i-1] == 's')
5744                 {
5745                         strcpy(&(dummy[i]), "es");
5746                         i++;
5747                 }
5748                 else
5749                 {
5750                         strcpy(&(dummy[i]), "s");
5751                 }
5752
5753                 strcpy(&(dummy[i+1]), aider);
5754                 strcpy(Name, dummy);
5755         }
5756         else if (my_strstr(Name, "coins"))
5757         {
5758                 char dummy[80];
5759                 strcpy(dummy, "piles of ");
5760                 strcat(dummy, Name);
5761                 strcpy(Name, dummy);
5762                 return;
5763         }
5764         else if (my_strstr(Name, "Manes"))
5765         {
5766                 return;
5767         }
5768         else if (streq(&(Name[NameLen - 2]), "ey"))
5769         {
5770                 strcpy(&(Name[NameLen - 2]), "eys");
5771         }
5772         else if (Name[NameLen - 1] == 'y')
5773         {
5774                 strcpy(&(Name[NameLen - 1]), "ies");
5775         }
5776         else if (streq(&(Name[NameLen - 4]), "ouse"))
5777         {
5778                 strcpy(&(Name[NameLen - 4]), "ice");
5779         }
5780         else if (streq(&(Name[NameLen - 2]), "us"))
5781         {
5782                 strcpy(&(Name[NameLen - 2]), "i");
5783         }
5784         else if (streq(&(Name[NameLen - 6]), "kelman"))
5785         {
5786                 strcpy(&(Name[NameLen - 6]), "kelmen");
5787         }
5788         else if (streq(&(Name[NameLen - 8]), "wordsman"))
5789         {
5790                 strcpy(&(Name[NameLen - 8]), "wordsmen");
5791         }
5792         else if (streq(&(Name[NameLen - 7]), "oodsman"))
5793         {
5794                 strcpy(&(Name[NameLen - 7]), "oodsmen");
5795         }
5796         else if (streq(&(Name[NameLen - 7]), "eastman"))
5797         {
5798                 strcpy(&(Name[NameLen - 7]), "eastmen");
5799         }
5800         else if (streq(&(Name[NameLen - 8]), "izardman"))
5801         {
5802                 strcpy(&(Name[NameLen - 8]), "izardmen");
5803         }
5804         else if (streq(&(Name[NameLen - 5]), "geist"))
5805         {
5806                 strcpy(&(Name[NameLen - 5]), "geister");
5807         }
5808         else if (streq(&(Name[NameLen - 2]), "ex"))
5809         {
5810                 strcpy(&(Name[NameLen - 2]), "ices");
5811         }
5812         else if (streq(&(Name[NameLen - 2]), "lf"))
5813         {
5814                 strcpy(&(Name[NameLen - 2]), "lves");
5815         }
5816         else if (suffix(Name, "ch") ||
5817                  suffix(Name, "sh") ||
5818                          suffix(Name, "nx") ||
5819                          suffix(Name, "s") ||
5820                          suffix(Name, "o"))
5821         {
5822                 strcpy(&(Name[NameLen]), "es");
5823         }
5824         else
5825         {
5826                 strcpy(&(Name[NameLen]), "s");
5827         }
5828 }
5829
5830 /*!
5831  * @brief 現在のペットを表示するコマンドのメインルーチン /
5832  * Display current pets
5833  * @return なし
5834  */
5835 static void do_cmd_knowledge_pets(void)
5836 {
5837         int             i;
5838         FILE            *fff;
5839         monster_type    *m_ptr;
5840         GAME_TEXT pet_name[MAX_NLEN];
5841         int             t_friends = 0;
5842         int             show_upkeep = 0;
5843         GAME_TEXT file_name[1024];
5844
5845
5846         /* Open a new file */
5847         fff = my_fopen_temp(file_name, 1024);
5848         if (!fff) {
5849             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5850             msg_print(NULL);
5851             return;
5852         }
5853
5854         /* Process the monsters (backwards) */
5855         for (i = m_max - 1; i >= 1; i--)
5856         {
5857                 /* Access the monster */
5858                 m_ptr = &m_list[i];
5859
5860                 /* Ignore "dead" monsters */
5861                 if (!m_ptr->r_idx) continue;
5862
5863                 /* Calculate "upkeep" for pets */
5864                 if (is_pet(m_ptr))
5865                 {
5866                         t_friends++;
5867                         monster_desc(pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
5868                         fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
5869                 }
5870         }
5871
5872         show_upkeep = calculate_upkeep();
5873
5874         fprintf(fff, "----------------------------------------------\n");
5875 #ifdef JP
5876         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
5877 #else
5878         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
5879 #endif
5880         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
5881
5882
5883         my_fclose(fff);
5884
5885         /* Display the file contents */
5886         show_file(TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
5887
5888         /* Remove the file */
5889         fd_kill(file_name);
5890 }
5891
5892
5893 /*!
5894  * @brief 現在のペットを表示するコマンドのメインルーチン /
5895  * Total kill count
5896  * @return なし
5897  * @note the player ghosts are ignored.  
5898  */
5899 static void do_cmd_knowledge_kill_count(void)
5900 {
5901         MONRACE_IDX i;
5902         int k, n = 0;
5903         u16b why = 2;
5904         MONRACE_IDX *who;
5905         FILE *fff;
5906         GAME_TEXT file_name[1024];
5907
5908         s32b Total = 0;
5909
5910
5911         /* Open a new file */
5912         fff = my_fopen_temp(file_name, 1024);
5913
5914         if (!fff) {
5915                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5916                 msg_print(NULL);
5917                 return;
5918         }
5919
5920         /* Allocate the "who" array */
5921         C_MAKE(who, max_r_idx, MONRACE_IDX);
5922
5923         {
5924                 /* Monsters slain */
5925                 int kk;
5926
5927                 for (kk = 1; kk < max_r_idx; kk++)
5928                 {
5929                         monster_race *r_ptr = &r_info[kk];
5930
5931                         if (r_ptr->flags1 & (RF1_UNIQUE))
5932                         {
5933                                 bool dead = (r_ptr->max_num == 0);
5934
5935                                 if (dead)
5936                                 {
5937                                         Total++;
5938                                 }
5939                         }
5940                         else
5941                         {
5942                                 MONSTER_NUMBER This = r_ptr->r_pkills;
5943
5944                                 if (This > 0)
5945                                 {
5946                                         Total += This;
5947                                 }
5948                         }
5949                 }
5950
5951                 if (Total < 1)
5952                         fprintf(fff,_("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
5953                 else
5954 #ifdef JP
5955                         fprintf(fff,"あなたは%ld体の敵を倒している。\n\n", (long int)Total);
5956 #else
5957                         fprintf(fff,"You have defeated %ld %s.\n\n", (long int)Total, (Total == 1) ? "enemy" : "enemies");
5958 #endif
5959         }
5960
5961         Total = 0;
5962
5963         /* Scan the monsters */
5964         for (i = 1; i < max_r_idx; i++)
5965         {
5966                 monster_race *r_ptr = &r_info[i];
5967
5968                 /* Use that monster */
5969                 if (r_ptr->name) who[n++] = i;
5970         }
5971
5972         /* Select the sort method */
5973         ang_sort_comp = ang_sort_comp_hook;
5974         ang_sort_swap = ang_sort_swap_hook;
5975
5976         /* Sort the array by dungeon depth of monsters */
5977         ang_sort(who, &why, n);
5978
5979         /* Scan the monster races */
5980         for (k = 0; k < n; k++)
5981         {
5982                 monster_race *r_ptr = &r_info[who[k]];
5983
5984                 if (r_ptr->flags1 & (RF1_UNIQUE))
5985                 {
5986                         bool dead = (r_ptr->max_num == 0);
5987
5988                         if (dead)
5989                         {
5990                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
5991                                 Total++;
5992                         }
5993                 }
5994                 else
5995                 {
5996                         MONSTER_NUMBER This = r_ptr->r_pkills;
5997
5998                         if (This > 0)
5999                         {
6000 #ifdef JP
6001                                 /* p,tは人と数える by ita */
6002                                 if (my_strchr("pt", r_ptr->d_char))
6003                                         fprintf(fff, "     %3d 人の %s\n", (int)This, r_name + r_ptr->name);
6004                                 else
6005                                         fprintf(fff, "     %3d 体の %s\n", (int)This, r_name + r_ptr->name);
6006 #else
6007                                 if (This < 2)
6008                                 {
6009                                         if (my_strstr(r_name + r_ptr->name, "coins"))
6010                                         {
6011                                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
6012                                         }
6013                                         else
6014                                         {
6015                                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
6016                                         }
6017                                 }
6018                                 else
6019                                 {
6020                                         char ToPlural[80];
6021                                         strcpy(ToPlural, (r_name + r_ptr->name));
6022                                         plural_aux(ToPlural);
6023                                         fprintf(fff, "     %d %s\n", This, ToPlural);
6024                                 }
6025 #endif
6026
6027
6028                                 Total += This;
6029                         }
6030                 }
6031         }
6032
6033         fprintf(fff,"----------------------------------------------\n");
6034 #ifdef JP
6035         fprintf(fff,"    合計: %lu 体を倒した。\n", (unsigned long int)Total);
6036 #else
6037         fprintf(fff,"   Total: %lu creature%s killed.\n", (unsigned long int)Total, (Total == 1 ? "" : "s"));
6038 #endif
6039
6040
6041         /* Free the "who" array */
6042         C_KILL(who, max_r_idx, s16b);
6043         my_fclose(fff);
6044
6045         /* Display the file contents */
6046         show_file(TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
6047
6048         /* Remove the file */
6049         fd_kill(file_name);
6050 }
6051
6052
6053 /*!
6054  * @brief モンスター情報リスト中のグループを表示する /
6055  * Display the object groups.
6056  * @param col 開始行
6057  * @param row 開始列
6058  * @param wid 表示文字数幅
6059  * @param per_page リストの表示行
6060  * @param grp_idx グループのID配列
6061  * @param group_text グループ名の文字列配列
6062  * @param grp_cur 現在の選択ID
6063  * @param grp_top 現在の選択リスト最上部ID
6064  * @return なし
6065  */
6066 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)
6067 {
6068         int i;
6069
6070         /* Display lines until done */
6071         for (i = 0; i < per_page && (grp_idx[i] >= 0); i++)
6072         {
6073                 /* Get the group index */
6074                 int grp = grp_idx[grp_top + i];
6075
6076                 /* Choose a color */
6077                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
6078
6079                 /* Erase the entire line */
6080                 Term_erase(col, row + i, wid);
6081
6082                 /* Display the group label */
6083                 c_put_str(attr, group_text[grp], row + i, col);
6084         }
6085 }
6086
6087
6088 /* 
6089  * Move the cursor in a browser window 
6090  */
6091 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, 
6092                                                    IDX *list_cur, int list_cnt)
6093 {
6094         int d;
6095         int col = *column;
6096         IDX grp = *grp_cur;
6097         IDX list = *list_cur;
6098
6099         /* Extract direction */
6100         if (ch == ' ')
6101         {
6102                 /* Hack -- scroll up full screen */
6103                 d = 3;
6104         }
6105         else if (ch == '-')
6106         {
6107                 /* Hack -- scroll down full screen */
6108                 d = 9;
6109         }
6110         else
6111         {
6112                 d = get_keymap_dir(ch);
6113         }
6114
6115         if (!d) return;
6116
6117         /* Diagonals - hack */
6118         if ((ddx[d] > 0) && ddy[d])
6119         {
6120                 int browser_rows;
6121                 int wid, hgt;
6122
6123                 Term_get_size(&wid, &hgt);
6124
6125                 browser_rows = hgt - 8;
6126
6127                 /* Browse group list */
6128                 if (!col)
6129                 {
6130                         int old_grp = grp;
6131
6132                         /* Move up or down */
6133                         grp += ddy[d] * (browser_rows - 1);
6134
6135                         /* Verify */
6136                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
6137                         if (grp < 0) grp = 0;
6138                         if (grp != old_grp)     list = 0;
6139                 }
6140
6141                 /* Browse sub-list list */
6142                 else
6143                 {
6144                         /* Move up or down */
6145                         list += ddy[d] * browser_rows;
6146
6147                         /* Verify */
6148                         if (list >= list_cnt) list = list_cnt - 1;
6149                         if (list < 0) list = 0;
6150                 }
6151
6152                 (*grp_cur) = grp;
6153                 (*list_cur) = list;
6154
6155                 return;
6156         }
6157
6158         if (ddx[d])
6159         {
6160                 col += ddx[d];
6161                 if (col < 0) col = 0;
6162                 if (col > 1) col = 1;
6163
6164                 (*column) = col;
6165
6166                 return;
6167         }
6168
6169         /* Browse group list */
6170         if (!col)
6171         {
6172                 int old_grp = grp;
6173
6174                 /* Move up or down */
6175                 grp += ddy[d];
6176
6177                 /* Verify */
6178                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
6179                 if (grp < 0) grp = 0;
6180                 if (grp != old_grp)     list = 0;
6181         }
6182
6183         /* Browse sub-list list */
6184         else
6185         {
6186                 /* Move up or down */
6187                 list += ddy[d];
6188
6189                 /* Verify */
6190                 if (list >= list_cnt) list = list_cnt - 1;
6191                 if (list < 0) list = 0;
6192         }
6193
6194         (*grp_cur) = grp;
6195         (*list_cur) = list;
6196 }
6197
6198
6199 /*
6200  * Display visuals.
6201  */
6202 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
6203 {
6204         int i, j;
6205
6206         /* Clear the display lines */
6207         for (i = 0; i < height; i++)
6208         {
6209                 Term_erase(col, row + i, width);
6210         }
6211
6212         /* Bigtile mode uses double width */
6213         if (use_bigtile) width /= 2;
6214
6215         /* Display lines until done */
6216         for (i = 0; i < height; i++)
6217         {
6218                 /* Display columns until done */
6219                 for (j = 0; j < width; j++)
6220                 {
6221                         byte a;
6222                         char c;
6223                         TERM_LEN x = col + j;
6224                         TERM_LEN y = row + i;
6225                         int ia, ic;
6226
6227                         /* Bigtile mode uses double width */
6228                         if (use_bigtile) x += j;
6229
6230                         ia = attr_top + i;
6231                         ic = char_left + j;
6232
6233                         /* Ignore illegal characters */
6234                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
6235                             (!use_graphics && ic > 0x7f))
6236                                 continue;
6237
6238                         a = (byte)ia;
6239                         c = (char)ic;
6240
6241                         /* Force correct code for both ASCII character and tile */
6242                         if (c & 0x80) a |= 0x80;
6243
6244                         /* Display symbol */
6245                         Term_queue_bigchar(x, y, a, c, 0, 0);
6246                 }
6247         }
6248 }
6249
6250
6251 /*
6252  * Place the cursor at the collect position for visual mode
6253  */
6254 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
6255 {
6256         int i = (a & 0x7f) - attr_top;
6257         int j = c - char_left;
6258
6259         TERM_LEN x = col + j;
6260         TERM_LEN y = row + i;
6261
6262         /* Bigtile mode uses double width */
6263         if (use_bigtile) x += j;
6264
6265         /* Place the cursor */
6266         Term_gotoxy(x, y);
6267 }
6268
6269
6270 /*
6271  *  Clipboard variables for copy&paste in visual mode
6272  */
6273 static TERM_COLOR attr_idx = 0;
6274 static byte char_idx = 0;
6275
6276 /* Hack -- for feature lighting */
6277 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
6278 static byte char_idx_feat[F_LIT_MAX];
6279
6280 /*
6281  *  Do visual mode command -- Change symbols
6282  */
6283 static bool visual_mode_command(char ch, bool *visual_list_ptr,
6284                                 int height, int width,
6285                                 TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
6286                                 TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
6287 {
6288         static TERM_COLOR attr_old = 0;
6289         static SYMBOL_CODE char_old = 0;
6290
6291         switch (ch)
6292         {
6293         case ESCAPE:
6294                 if (*visual_list_ptr)
6295                 {
6296                         /* Cancel change */
6297                         *cur_attr_ptr = attr_old;
6298                         *cur_char_ptr = char_old;
6299                         *visual_list_ptr = FALSE;
6300
6301                         return TRUE;
6302                 }
6303                 break;
6304
6305         case '\n':
6306         case '\r':
6307                 if (*visual_list_ptr)
6308                 {
6309                         /* Accept change */
6310                         *visual_list_ptr = FALSE;
6311                         *need_redraw = TRUE;
6312
6313                         return TRUE;
6314                 }
6315                 break;
6316
6317         case 'V':
6318         case 'v':
6319                 if (!*visual_list_ptr)
6320                 {
6321                         *visual_list_ptr = TRUE;
6322
6323                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6324                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6325
6326                         attr_old = *cur_attr_ptr;
6327                         char_old = *cur_char_ptr;
6328
6329                         return TRUE;
6330                 }
6331                 break;
6332
6333         case 'C':
6334         case 'c':
6335                 {
6336                         int i;
6337
6338                         /* Set the visual */
6339                         attr_idx = *cur_attr_ptr;
6340                         char_idx = *cur_char_ptr;
6341
6342                         /* Hack -- for feature lighting */
6343                         for (i = 0; i < F_LIT_MAX; i++)
6344                         {
6345                                 attr_idx_feat[i] = 0;
6346                                 char_idx_feat[i] = 0;
6347                         }
6348                 }
6349                 return TRUE;
6350
6351         case 'P':
6352         case 'p':
6353                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
6354                 {
6355                         /* Set the char */
6356                         *cur_attr_ptr = attr_idx;
6357                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6358                         if (!*visual_list_ptr) *need_redraw = TRUE;
6359                 }
6360
6361                 if (char_idx)
6362                 {
6363                         /* Set the char */
6364                         *cur_char_ptr = char_idx;
6365                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6366                         if (!*visual_list_ptr) *need_redraw = TRUE;
6367                 }
6368
6369                 return TRUE;
6370
6371         default:
6372                 if (*visual_list_ptr)
6373                 {
6374                         int eff_width;
6375                         int d = get_keymap_dir(ch);
6376                         byte a = (*cur_attr_ptr & 0x7f);
6377                         byte c = *cur_char_ptr;
6378
6379                         if (use_bigtile) eff_width = width / 2;
6380                         else eff_width = width;
6381
6382                         /* Restrict direction */
6383                         if ((a == 0) && (ddy[d] < 0)) d = 0;
6384                         if ((c == 0) && (ddx[d] < 0)) d = 0;
6385                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
6386                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
6387
6388                         a += ddy[d];
6389                         c += ddx[d];
6390
6391                         /* Force correct code for both ASCII character and tile */
6392                         if (c & 0x80) a |= 0x80;
6393
6394                         /* Set the visual */
6395                         *cur_attr_ptr = a;
6396                         *cur_char_ptr = c;
6397
6398
6399                         /* Move the frame */
6400                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
6401                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
6402                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
6403                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
6404                         return TRUE;
6405                 }
6406                 break;
6407         }
6408
6409         /* Visual mode command is not used */
6410         return FALSE;
6411 }
6412
6413
6414 /*
6415  * Display the monsters in a group.
6416  */
6417 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
6418         int mon_cur, int mon_top, bool visual_only)
6419 {
6420         int i;
6421
6422         /* Display lines until done */
6423         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
6424         {
6425                 TERM_COLOR attr;
6426
6427                 /* Get the race index */
6428                 MONRACE_IDX r_idx = mon_idx[mon_top + i] ;
6429
6430                 /* Access the race */
6431                 monster_race *r_ptr = &r_info[r_idx];
6432
6433                 /* Choose a color */
6434                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
6435
6436                 /* Display the name */
6437                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
6438
6439                 /* Hack -- visual_list mode */
6440                 if (per_page == 1)
6441                 {
6442                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61);
6443                 }
6444                 if (p_ptr->wizard || visual_only)
6445                 {
6446                         c_prt(attr, format("%d", r_idx), row + i, 62);
6447                 }
6448
6449                 /* Erase chars before overwritten by the race letter */
6450                 Term_erase(69, row + i, 255);
6451
6452                 /* Display symbol */
6453                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
6454
6455                 if (!visual_only)
6456                 {
6457                         /* Display kills */
6458                         if (!(r_ptr->flags1 & RF1_UNIQUE)) 
6459                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
6460                         else 
6461                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), 
6462                                                   (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
6463                 }
6464         }
6465
6466         /* Clear remaining lines */
6467         for (; i < per_page; i++)
6468         {
6469                 Term_erase(col, row + i, 255);
6470         }
6471 }
6472
6473
6474 /*
6475  * Display known monsters.
6476  */
6477 static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, IDX direct_r_idx)
6478 {
6479         IDX i;
6480         int len, max;
6481         IDX grp_cur, grp_top, old_grp_cur;
6482         IDX mon_cur, mon_top;
6483         IDX grp_cnt, grp_idx[100];
6484         IDX mon_cnt;
6485         IDX *mon_idx;
6486
6487         int column = 0;
6488         bool flag;
6489         bool redraw;
6490
6491         bool visual_list = FALSE;
6492         TERM_COLOR attr_top = 0;
6493         byte char_left = 0;
6494
6495         int browser_rows;
6496         TERM_LEN wid, hgt;
6497
6498         BIT_FLAGS8 mode;
6499
6500         Term_get_size(&wid, &hgt);
6501
6502         browser_rows = hgt - 8;
6503
6504         /* Allocate the "mon_idx" array */
6505         C_MAKE(mon_idx, max_r_idx, s16b);
6506
6507         max = 0;
6508         grp_cnt = 0;
6509
6510         if (direct_r_idx < 0)
6511         {
6512                 mode = visual_only ? 0x03 : 0x01;
6513
6514                 /* Check every group */
6515                 for (i = 0; monster_group_text[i] != NULL; i++)
6516                 {
6517                         /* Measure the label */
6518                         len = strlen(monster_group_text[i]);
6519
6520                         /* Save the maximum length */
6521                         if (len > max) max = len;
6522
6523                         /* See if any monsters are known */
6524                         if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode))
6525                         {
6526                                 /* Build a list of groups with known monsters */
6527                                 grp_idx[grp_cnt++] = i;
6528                         }
6529                 }
6530
6531                 mon_cnt = 0;
6532         }
6533         else
6534         {
6535                 mon_idx[0] = direct_r_idx;
6536                 mon_cnt = 1;
6537
6538                 /* Terminate the list */
6539                 mon_idx[1] = -1;
6540
6541                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6542                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
6543         }
6544
6545         /* Terminate the list */
6546         grp_idx[grp_cnt] = -1;
6547
6548         old_grp_cur = -1;
6549         grp_cur = grp_top = 0;
6550         mon_cur = mon_top = 0;
6551
6552         flag = FALSE;
6553         redraw = TRUE;
6554
6555         mode = visual_only ? 0x02 : 0x00;
6556
6557         while (!flag)
6558         {
6559                 char ch;
6560                 monster_race *r_ptr;
6561
6562                 if (redraw)
6563                 {
6564                         clear_from(0);
6565                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
6566                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
6567                         prt(_("名前", "Name"), 4, max + 3);
6568                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6569                         prt(_("文字", "Sym"), 4, 67);
6570                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
6571
6572                         for (i = 0; i < 78; i++)
6573                         {
6574                                 Term_putch(i, 5, TERM_WHITE, '=');
6575                         }
6576
6577                         if (direct_r_idx < 0)
6578                         {
6579                                 for (i = 0; i < browser_rows; i++)
6580                                 {
6581                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6582                                 }
6583                         }
6584
6585                         redraw = FALSE;
6586                 }
6587
6588                 if (direct_r_idx < 0)
6589                 {
6590                         /* Scroll group list */
6591                         if (grp_cur < grp_top) grp_top = grp_cur;
6592                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6593
6594                         /* Display a list of monster groups */
6595                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
6596
6597                         if (old_grp_cur != grp_cur)
6598                         {
6599                                 old_grp_cur = grp_cur;
6600
6601                                 /* Get a list of monsters in the current group */
6602                                 mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode);
6603                         }
6604
6605                         /* Scroll monster list */
6606                         while (mon_cur < mon_top)
6607                                 mon_top = MAX(0, mon_top - browser_rows/2);
6608                         while (mon_cur >= mon_top + browser_rows)
6609                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
6610                 }
6611
6612                 if (!visual_list)
6613                 {
6614                         /* Display a list of monsters in the current group */
6615                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
6616                 }
6617                 else
6618                 {
6619                         mon_top = mon_cur;
6620
6621                         /* Display a monster name */
6622                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
6623
6624                         /* Display visual list below first monster */
6625                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
6626                 }
6627
6628                 /* Prompt */
6629                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
6630                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
6631                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
6632                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
6633                         hgt - 1, 0);
6634
6635                 /* Get the current monster */
6636                 r_ptr = &r_info[mon_idx[mon_cur]];
6637
6638                 if (!visual_only)
6639                 {
6640                         /* Mega Hack -- track this monster race */
6641                         if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
6642                         handle_stuff();
6643                 }
6644
6645                 if (visual_list)
6646                 {
6647                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
6648                 }
6649                 else if (!column)
6650                 {
6651                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
6652                 }
6653                 else
6654                 {
6655                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
6656                 }
6657
6658                 ch = inkey();
6659
6660                 /* Do visual mode command if needed */
6661                 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))
6662                 {
6663                         if (direct_r_idx >= 0)
6664                         {
6665                                 switch (ch)
6666                                 {
6667                                 case '\n':
6668                                 case '\r':
6669                                 case ESCAPE:
6670                                         flag = TRUE;
6671                                         break;
6672                                 }
6673                         }
6674                         continue;
6675                 }
6676
6677                 switch (ch)
6678                 {
6679                         case ESCAPE:
6680                         {
6681                                 flag = TRUE;
6682                                 break;
6683                         }
6684
6685                         case 'R':
6686                         case 'r':
6687                         {
6688                                 /* Recall on screen */
6689                                 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
6690                                 {
6691                                         screen_roff(mon_idx[mon_cur], 0);
6692
6693                                         (void)inkey();
6694
6695                                         redraw = TRUE;
6696                                 }
6697                                 break;
6698                         }
6699
6700                         default:
6701                         {
6702                                 /* Move the cursor */
6703                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
6704
6705                                 break;
6706                         }
6707                 }
6708         }
6709
6710         /* Free the "mon_idx" array */
6711         C_KILL(mon_idx, max_r_idx, s16b);
6712 }
6713
6714
6715 /*
6716  * Display the objects in a group.
6717  */
6718 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
6719         int object_cur, int object_top, bool visual_only)
6720 {
6721         int i;
6722
6723         /* Display lines until done */
6724         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
6725         {
6726                 GAME_TEXT o_name[MAX_NLEN];
6727                 TERM_COLOR a;
6728                 byte c;
6729                 object_kind *flavor_k_ptr;
6730
6731                 /* Get the object index */
6732                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
6733
6734                 /* Access the object */
6735                 object_kind *k_ptr = &k_info[k_idx];
6736
6737                 /* Choose a color */
6738                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
6739                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
6740
6741
6742                 if (!visual_only && k_ptr->flavor)
6743                 {
6744                         /* Appearance of this object is shuffled */
6745                         flavor_k_ptr = &k_info[k_ptr->flavor];
6746                 }
6747                 else
6748                 {
6749                         /* Appearance of this object is very normal */
6750                         flavor_k_ptr = k_ptr;
6751                 }
6752
6753
6754
6755                 attr = ((i + object_top == object_cur) ? cursor : attr);
6756
6757                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
6758                 {
6759                         /* Tidy name */
6760                         strip_name(o_name, k_idx);
6761                 }
6762                 else
6763                 {
6764                         /* Flavor name */
6765                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
6766                 }
6767
6768                 /* Display the name */
6769                 c_prt(attr, o_name, row + i, col);
6770
6771                 /* Hack -- visual_list mode */
6772                 if (per_page == 1)
6773                 {
6774                         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);
6775                 }
6776                 if (p_ptr->wizard || visual_only)
6777                 {
6778                         c_prt(attr, format("%d", k_idx), row + i, 70);
6779                 }
6780
6781                 a = flavor_k_ptr->x_attr;
6782                 c = flavor_k_ptr->x_char;
6783
6784                 /* Display symbol */
6785                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
6786         }
6787
6788         /* Clear remaining lines */
6789         for (; i < per_page; i++)
6790         {
6791                 Term_erase(col, row + i, 255);
6792         }
6793 }
6794
6795 /*
6796  * Describe fake object
6797  */
6798 static void desc_obj_fake(KIND_OBJECT_IDX k_idx)
6799 {
6800         object_type *o_ptr;
6801         object_type object_type_body;
6802         o_ptr = &object_type_body;
6803         object_wipe(o_ptr);
6804
6805         /* Create the artifact */
6806         object_prep(o_ptr, k_idx);
6807
6808         /* It's fully know */
6809         o_ptr->ident |= IDENT_KNOWN;
6810
6811         /* Track the object */
6812         /* object_actual_track(o_ptr); */
6813
6814         /* Hack - mark as fake */
6815         /* term_obj_real = FALSE; */
6816         handle_stuff();
6817
6818         if (!screen_object(o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL))
6819         {
6820                 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
6821                 msg_print(NULL);
6822         }
6823 }
6824
6825
6826
6827 /*
6828  * Display known objects
6829  */
6830 static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, IDX direct_k_idx)
6831 {
6832         IDX i;
6833         int len, max;
6834         IDX grp_cur, grp_top, old_grp_cur;
6835         IDX object_old, object_cur, object_top;
6836         int grp_cnt;
6837         IDX grp_idx[100];
6838         int object_cnt;
6839         IDX *object_idx;
6840
6841         int column = 0;
6842         bool flag;
6843         bool redraw;
6844
6845         bool visual_list = FALSE;
6846         TERM_COLOR attr_top = 0;
6847         byte char_left = 0;
6848
6849         int browser_rows;
6850         int wid, hgt;
6851
6852         byte mode;
6853
6854         Term_get_size(&wid, &hgt);
6855
6856         browser_rows = hgt - 8;
6857
6858         /* Allocate the "object_idx" array */
6859         C_MAKE(object_idx, max_k_idx, IDX);
6860
6861         max = 0;
6862         grp_cnt = 0;
6863
6864         if (direct_k_idx < 0)
6865         {
6866                 mode = visual_only ? 0x03 : 0x01;
6867
6868                 /* Check every group */
6869                 for (i = 0; object_group_text[i] != NULL; i++)
6870                 {
6871                         /* Measure the label */
6872                         len = strlen(object_group_text[i]);
6873
6874                         /* Save the maximum length */
6875                         if (len > max) max = len;
6876
6877                         /* See if any monsters are known */
6878                         if (collect_objects(i, object_idx, mode))
6879                         {
6880                                 /* Build a list of groups with known monsters */
6881                                 grp_idx[grp_cnt++] = i;
6882                         }
6883                 }
6884
6885                 object_old = -1;
6886                 object_cnt = 0;
6887         }
6888         else
6889         {
6890                 object_kind *k_ptr = &k_info[direct_k_idx];
6891                 object_kind *flavor_k_ptr;
6892
6893                 if (!visual_only && k_ptr->flavor)
6894                 {
6895                         /* Appearance of this object is shuffled */
6896                         flavor_k_ptr = &k_info[k_ptr->flavor];
6897                 }
6898                 else
6899                 {
6900                         /* Appearance of this object is very normal */
6901                         flavor_k_ptr = k_ptr;
6902                 }
6903
6904                 object_idx[0] = direct_k_idx;
6905                 object_old = direct_k_idx;
6906                 object_cnt = 1;
6907
6908                 /* Terminate the list */
6909                 object_idx[1] = -1;
6910
6911                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6912                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
6913         }
6914
6915         /* Terminate the list */
6916         grp_idx[grp_cnt] = -1;
6917
6918         old_grp_cur = -1;
6919         grp_cur = grp_top = 0;
6920         object_cur = object_top = 0;
6921
6922         flag = FALSE;
6923         redraw = TRUE;
6924
6925         mode = visual_only ? 0x02 : 0x00;
6926
6927         while (!flag)
6928         {
6929                 char ch;
6930                 object_kind *k_ptr, *flavor_k_ptr;
6931
6932                 if (redraw)
6933                 {
6934                         clear_from(0);
6935
6936 #ifdef JP
6937                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
6938                         if (direct_k_idx < 0) prt("グループ", 4, 0);
6939                         prt("名前", 4, max + 3);
6940                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6941                         prt("文字", 4, 74);
6942 #else
6943                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
6944                         if (direct_k_idx < 0) prt("Group", 4, 0);
6945                         prt("Name", 4, max + 3);
6946                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6947                         prt("Sym", 4, 75);
6948 #endif
6949
6950                         for (i = 0; i < 78; i++)
6951                         {
6952                                 Term_putch(i, 5, TERM_WHITE, '=');
6953                         }
6954
6955                         if (direct_k_idx < 0)
6956                         {
6957                                 for (i = 0; i < browser_rows; i++)
6958                                 {
6959                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6960                                 }
6961                         }
6962
6963                         redraw = FALSE;
6964                 }
6965
6966                 if (direct_k_idx < 0)
6967                 {
6968                         /* Scroll group list */
6969                         if (grp_cur < grp_top) grp_top = grp_cur;
6970                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6971
6972                         /* Display a list of object groups */
6973                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
6974
6975                         if (old_grp_cur != grp_cur)
6976                         {
6977                                 old_grp_cur = grp_cur;
6978
6979                                 /* Get a list of objects in the current group */
6980                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
6981                         }
6982
6983                         /* Scroll object list */
6984                         while (object_cur < object_top)
6985                                 object_top = MAX(0, object_top - browser_rows/2);
6986                         while (object_cur >= object_top + browser_rows)
6987                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
6988                 }
6989
6990                 if (!visual_list)
6991                 {
6992                         /* Display a list of objects in the current group */
6993                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
6994                 }
6995                 else
6996                 {
6997                         object_top = object_cur;
6998
6999                         /* Display a list of objects in the current group */
7000                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
7001
7002                         /* Display visual list below first object */
7003                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7004                 }
7005
7006                 /* Get the current object */
7007                 k_ptr = &k_info[object_idx[object_cur]];
7008
7009                 if (!visual_only && k_ptr->flavor)
7010                 {
7011                         /* Appearance of this object is shuffled */
7012                         flavor_k_ptr = &k_info[k_ptr->flavor];
7013                 }
7014                 else
7015                 {
7016                         /* Appearance of this object is very normal */
7017                         flavor_k_ptr = k_ptr;
7018                 }
7019
7020                 /* Prompt */
7021 #ifdef JP
7022                 prt(format("<方向>%s%s%s, ESC",
7023                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
7024                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
7025                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
7026                         hgt - 1, 0);
7027 #else
7028                 prt(format("<dir>%s%s%s, ESC",
7029                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
7030                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
7031                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7032                         hgt - 1, 0);
7033 #endif
7034
7035                 if (!visual_only)
7036                 {
7037                         /* Mega Hack -- track this object */
7038                         if (object_cnt) object_kind_track(object_idx[object_cur]);
7039
7040                         /* The "current" object changed */
7041                         if (object_old != object_idx[object_cur])
7042                         {
7043                                 handle_stuff();
7044
7045                                 /* Remember the "current" object */
7046                                 object_old = object_idx[object_cur];
7047                         }
7048                 }
7049
7050                 if (visual_list)
7051                 {
7052                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
7053                 }
7054                 else if (!column)
7055                 {
7056                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7057                 }
7058                 else
7059                 {
7060                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
7061                 }
7062
7063                 ch = inkey();
7064
7065                 /* Do visual mode command if needed */
7066                 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))
7067                 {
7068                         if (direct_k_idx >= 0)
7069                         {
7070                                 switch (ch)
7071                                 {
7072                                 case '\n':
7073                                 case '\r':
7074                                 case ESCAPE:
7075                                         flag = TRUE;
7076                                         break;
7077                                 }
7078                         }
7079                         continue;
7080                 }
7081
7082                 switch (ch)
7083                 {
7084                         case ESCAPE:
7085                         {
7086                                 flag = TRUE;
7087                                 break;
7088                         }
7089
7090                         case 'R':
7091                         case 'r':
7092                         {
7093                                 /* Recall on screen */
7094                                 if (!visual_list && !visual_only && (grp_cnt > 0))
7095                                 {
7096                                         desc_obj_fake(object_idx[object_cur]);
7097                                         redraw = TRUE;
7098                                 }
7099                                 break;
7100                         }
7101
7102                         default:
7103                         {
7104                                 /* Move the cursor */
7105                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
7106                                 break;
7107                         }
7108                 }
7109         }
7110
7111         /* Free the "object_idx" array */
7112         C_KILL(object_idx, max_k_idx, IDX);
7113 }
7114
7115
7116 /*
7117  * Display the features in a group.
7118  */
7119 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
7120         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
7121 {
7122         int lit_col[F_LIT_MAX], i, j;
7123         int f_idx_col = use_bigtile ? 62 : 64;
7124
7125         /* Correct columns 1 and 4 */
7126         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
7127         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7128                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
7129
7130         /* Display lines until done */
7131         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
7132         {
7133                 TERM_COLOR attr;
7134
7135                 /* Get the index */
7136                 FEAT_IDX f_idx = feat_idx[feat_top + i];
7137
7138                 /* Access the index */
7139                 feature_type *f_ptr = &f_info[f_idx];
7140
7141                 int row_i = row + i;
7142
7143                 /* Choose a color */
7144                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
7145
7146                 /* Display the name */
7147                 c_prt(attr, f_name + f_ptr->name, row_i, col);
7148
7149                 /* Hack -- visual_list mode */
7150                 if (per_page == 1)
7151                 {
7152                         /* Display lighting level */
7153                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
7154
7155                         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));
7156                 }
7157                 if (p_ptr->wizard || visual_only)
7158                 {
7159                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
7160                 }
7161
7162                 /* Display symbol */
7163                 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);
7164
7165                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
7166                 for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
7167                 {
7168                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
7169                 }
7170                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
7171
7172                 /* Mega-hack -- Use non-standard colour */
7173                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
7174                 {
7175                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
7176                 }
7177         }
7178
7179         /* Clear remaining lines */
7180         for (; i < per_page; i++)
7181         {
7182                 Term_erase(col, row + i, 255);
7183         }
7184 }
7185
7186
7187 /*
7188  * Interact with feature visuals.
7189  */
7190 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
7191 {
7192         FEAT_IDX i;
7193         int len, max;
7194         FEAT_IDX grp_cur, grp_top, old_grp_cur;
7195         FEAT_IDX feat_cur, feat_top;
7196         int grp_cnt;
7197         FEAT_IDX grp_idx[100];
7198         int feat_cnt;
7199         FEAT_IDX *feat_idx;
7200
7201         TERM_LEN column = 0;
7202         bool flag;
7203         bool redraw;
7204
7205         bool visual_list = FALSE;
7206         TERM_COLOR attr_top = 0;
7207         byte char_left = 0;
7208
7209         TERM_LEN browser_rows;
7210         TERM_LEN wid, hgt;
7211
7212         TERM_COLOR attr_old[F_LIT_MAX];
7213         SYMBOL_CODE char_old[F_LIT_MAX];
7214         TERM_COLOR *cur_attr_ptr;
7215         SYMBOL_CODE *cur_char_ptr;
7216
7217         (void)C_WIPE(attr_old, F_LIT_MAX, byte);
7218         (void)C_WIPE(char_old, F_LIT_MAX, byte);
7219
7220         Term_get_size(&wid, &hgt);
7221
7222         browser_rows = hgt - 8;
7223
7224         /* Allocate the "feat_idx" array */
7225         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
7226
7227         max = 0;
7228         grp_cnt = 0;
7229
7230         if (direct_f_idx < 0)
7231         {
7232                 /* Check every group */
7233                 for (i = 0; feature_group_text[i] != NULL; i++)
7234                 {
7235                         /* Measure the label */
7236                         len = strlen(feature_group_text[i]);
7237
7238                         /* Save the maximum length */
7239                         if (len > max) max = len;
7240
7241                         /* See if any features are known */
7242                         if (collect_features(i, feat_idx, 0x01))
7243                         {
7244                                 /* Build a list of groups with known features */
7245                                 grp_idx[grp_cnt++] = i;
7246                         }
7247                 }
7248
7249                 feat_cnt = 0;
7250         }
7251         else
7252         {
7253                 feature_type *f_ptr = &f_info[direct_f_idx];
7254
7255                 feat_idx[0] = direct_f_idx;
7256                 feat_cnt = 1;
7257
7258                 /* Terminate the list */
7259                 feat_idx[1] = -1;
7260
7261                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
7262                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
7263
7264                 for (i = 0; i < F_LIT_MAX; i++)
7265                 {
7266                         attr_old[i] = f_ptr->x_attr[i];
7267                         char_old[i] = f_ptr->x_char[i];
7268                 }
7269         }
7270
7271         /* Terminate the list */
7272         grp_idx[grp_cnt] = -1;
7273
7274         old_grp_cur = -1;
7275         grp_cur = grp_top = 0;
7276         feat_cur = feat_top = 0;
7277
7278         flag = FALSE;
7279         redraw = TRUE;
7280
7281         while (!flag)
7282         {
7283                 char ch;
7284                 feature_type *f_ptr;
7285
7286                 if (redraw)
7287                 {
7288                         clear_from(0);
7289
7290                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
7291                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
7292                         prt(_("名前", "Name"), 4, max + 3);
7293                         if (use_bigtile)
7294                         {
7295                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7296                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
7297                         }
7298                         else
7299                         {
7300                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7301                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
7302                         }
7303
7304                         for (i = 0; i < 78; i++)
7305                         {
7306                                 Term_putch(i, 5, TERM_WHITE, '=');
7307                         }
7308
7309                         if (direct_f_idx < 0)
7310                         {
7311                                 for (i = 0; i < browser_rows; i++)
7312                                 {
7313                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
7314                                 }
7315                         }
7316
7317                         redraw = FALSE;
7318                 }
7319
7320                 if (direct_f_idx < 0)
7321                 {
7322                         /* Scroll group list */
7323                         if (grp_cur < grp_top) grp_top = grp_cur;
7324                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
7325
7326                         /* Display a list of feature groups */
7327                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
7328
7329                         if (old_grp_cur != grp_cur)
7330                         {
7331                                 old_grp_cur = grp_cur;
7332
7333                                 /* Get a list of features in the current group */
7334                                 feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00);
7335                         }
7336
7337                         /* Scroll feature list */
7338                         while (feat_cur < feat_top)
7339                                 feat_top = MAX(0, feat_top - browser_rows/2);
7340                         while (feat_cur >= feat_top + browser_rows)
7341                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
7342                 }
7343
7344                 if (!visual_list)
7345                 {
7346                         /* Display a list of features in the current group */
7347                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
7348                 }
7349                 else
7350                 {
7351                         feat_top = feat_cur;
7352
7353                         /* Display a list of features in the current group */
7354                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
7355
7356                         /* Display visual list below first object */
7357                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7358                 }
7359
7360                 /* Prompt */
7361                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
7362                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
7363                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
7364                         hgt - 1, 0);
7365
7366                 /* Get the current feature */
7367                 f_ptr = &f_info[feat_idx[feat_cur]];
7368                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
7369                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
7370
7371                 if (visual_list)
7372                 {
7373                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
7374                 }
7375                 else if (!column)
7376                 {
7377                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7378                 }
7379                 else
7380                 {
7381                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
7382                 }
7383
7384                 ch = inkey();
7385
7386                 if (visual_list && ((ch == 'A') || (ch == 'a')))
7387                 {
7388                         int prev_lighting_level = *lighting_level;
7389
7390                         if (ch == 'A')
7391                         {
7392                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
7393                                 else (*lighting_level)--;
7394                         }
7395                         else
7396                         {
7397                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
7398                                 else (*lighting_level)++;
7399                         }
7400
7401                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
7402                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7403
7404                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
7405                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7406
7407                         continue;
7408                 }
7409
7410                 else if ((ch == 'D') || (ch == 'd'))
7411                 {
7412                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
7413                         byte prev_x_char = f_ptr->x_char[*lighting_level];
7414
7415                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
7416
7417                         if (visual_list)
7418                         {
7419                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
7420                                          attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7421
7422                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
7423                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7424                         }
7425                         else *need_redraw = TRUE;
7426
7427                         continue;
7428                 }
7429
7430                 /* Do visual mode command if needed */
7431                 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))
7432                 {
7433                         switch (ch)
7434                         {
7435                         /* Restore previous visual settings */
7436                         case ESCAPE:
7437                                 for (i = 0; i < F_LIT_MAX; i++)
7438                                 {
7439                                         f_ptr->x_attr[i] = attr_old[i];
7440                                         f_ptr->x_char[i] = char_old[i];
7441                                 }
7442
7443                                 /* Fall through */
7444
7445                         case '\n':
7446                         case '\r':
7447                                 if (direct_f_idx >= 0) flag = TRUE;
7448                                 else *lighting_level = F_LIT_STANDARD;
7449                                 break;
7450
7451                         /* Preserve current visual settings */
7452                         case 'V':
7453                         case 'v':
7454                                 for (i = 0; i < F_LIT_MAX; i++)
7455                                 {
7456                                         attr_old[i] = f_ptr->x_attr[i];
7457                                         char_old[i] = f_ptr->x_char[i];
7458                                 }
7459                                 *lighting_level = F_LIT_STANDARD;
7460                                 break;
7461
7462                         case 'C':
7463                         case 'c':
7464                                 if (!visual_list)
7465                                 {
7466                                         for (i = 0; i < F_LIT_MAX; i++)
7467                                         {
7468                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
7469                                                 char_idx_feat[i] = f_ptr->x_char[i];
7470                                         }
7471                                 }
7472                                 break;
7473
7474                         case 'P':
7475                         case 'p':
7476                                 if (!visual_list)
7477                                 {
7478                                         /* Allow TERM_DARK text */
7479                                         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7480                                         {
7481                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
7482                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
7483                                         }
7484                                 }
7485                                 break;
7486                         }
7487                         continue;
7488                 }
7489
7490                 switch (ch)
7491                 {
7492                         case ESCAPE:
7493                         {
7494                                 flag = TRUE;
7495                                 break;
7496                         }
7497
7498                         default:
7499                         {
7500                                 /* Move the cursor */
7501                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
7502                                 break;
7503                         }
7504                 }
7505         }
7506
7507         /* Free the "feat_idx" array */
7508         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
7509 }
7510
7511
7512 /*
7513  * List wanted monsters
7514  */
7515 static void do_cmd_knowledge_kubi(void)
7516 {
7517         int i;
7518         FILE *fff;
7519         
7520         GAME_TEXT file_name[1024];
7521         
7522         
7523         /* Open a new file */
7524         fff = my_fopen_temp(file_name, 1024);
7525         if (!fff) {
7526             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7527             msg_print(NULL);
7528             return;
7529         }
7530         
7531         if (fff)
7532         {
7533                 bool listed = FALSE;
7534
7535 #ifdef JP
7536                 fprintf(fff, "今日のターゲット : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "不明"));
7537                 fprintf(fff, "\n");
7538                 fprintf(fff, "賞金首リスト\n");
7539 #else
7540                 fprintf(fff, "Today target : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "unknown"));
7541                 fprintf(fff, "\n");
7542                 fprintf(fff, "List of wanted monsters\n");
7543 #endif
7544                 fprintf(fff, "----------------------------------------------\n");
7545
7546                 for (i = 0; i < MAX_KUBI; i++)
7547                 {
7548                         if (kubi_r_idx[i] <= 10000)
7549                         {
7550                                 fprintf(fff,"%s\n", r_name + r_info[kubi_r_idx[i]].name);
7551
7552                                 listed = TRUE;
7553                         }
7554                 }
7555
7556                 if (!listed)
7557                 {
7558                         fprintf(fff,"\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster."));
7559                 }
7560         }
7561                 my_fclose(fff);
7562         
7563         /* Display the file contents */
7564         show_file(TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
7565         
7566         /* Remove the file */
7567         fd_kill(file_name);
7568 }
7569
7570 /*
7571  * List virtues & status
7572  */
7573 static void do_cmd_knowledge_virtues(void)
7574 {
7575         FILE *fff;      
7576         GAME_TEXT file_name[1024];
7577                 
7578         /* Open a new file */
7579         fff = my_fopen_temp(file_name, 1024);
7580         if (!fff) {
7581             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7582             msg_print(NULL);
7583             return;
7584         }
7585         
7586         if (fff)
7587         {
7588                 fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment());
7589                 dump_virtues(fff);
7590         }
7591                 my_fclose(fff);
7592         
7593         /* Display the file contents */
7594         show_file(TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
7595         
7596         /* Remove the file */
7597         fd_kill(file_name);
7598 }
7599
7600 /*
7601 * Dungeon
7602 *
7603 */
7604 static void do_cmd_knowledge_dungeon(void)
7605 {
7606         FILE *fff;
7607         
7608         GAME_TEXT file_name[1024];
7609         int i;
7610                 
7611         /* Open a new file */
7612         fff = my_fopen_temp(file_name, 1024);
7613         if (!fff) {
7614             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7615             msg_print(NULL);
7616             return;
7617         }
7618         
7619         if (fff)
7620         {
7621                 for (i = 1; i < max_d_idx; i++)
7622                 {
7623                         bool seiha = FALSE;
7624
7625                         if (!d_info[i].maxdepth) continue;
7626                         if (!max_dlv[i]) continue;
7627                         if (d_info[i].final_guardian)
7628                         {
7629                                 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
7630                         }
7631                         else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
7632                         
7633                         fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
7634                 }
7635         }
7636                 my_fclose(fff);
7637         
7638         /* Display the file contents */
7639         show_file(TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
7640         
7641         /* Remove the file */
7642         fd_kill(file_name);
7643 }
7644
7645 /*
7646 * List virtues & status
7647 *
7648 */
7649 static void do_cmd_knowledge_stat(void)
7650 {
7651         FILE *fff;
7652         
7653         GAME_TEXT file_name[1024];
7654         int percent, v_nr;
7655         
7656         /* Open a new file */
7657         fff = my_fopen_temp(file_name, 1024);
7658         if (!fff) {
7659             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7660             msg_print(NULL);
7661             return;
7662         }
7663         
7664         if (fff)
7665         {
7666                 percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
7667                         (2 * p_ptr->hitdie +
7668                         ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
7669
7670 #ifdef JP
7671                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "現在の体力ランク : %d/100\n\n", percent);
7672                 else fprintf(fff, "現在の体力ランク : ???\n\n");
7673                 fprintf(fff, "能力の最大値\n\n");
7674 #else
7675                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "Your current Life Rating is %d/100.\n\n", percent);
7676                 else fprintf(fff, "Your current Life Rating is ???.\n\n");
7677                 fprintf(fff, "Limits of maximum stats\n\n");
7678 #endif
7679                 for (v_nr = 0; v_nr < 6; v_nr++)
7680                 {
7681                         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);
7682                         else fprintf(fff, "%s ???\n", stat_names[v_nr]);
7683                 }
7684         }
7685
7686         dump_yourself(fff);
7687         my_fclose(fff);
7688         
7689         /* Display the file contents */
7690         show_file(TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
7691         
7692         /* Remove the file */
7693         fd_kill(file_name);
7694 }
7695
7696
7697 /*
7698  * Print all active quests
7699  */
7700 static void do_cmd_knowledge_quests_current(FILE *fff)
7701 {
7702         char tmp_str[120];
7703         char rand_tmp_str[120] = "\0";
7704         GAME_TEXT name[MAX_NLEN];
7705         monster_race *r_ptr;
7706         IDX i;
7707         int rand_level = 100;
7708         int total = 0;
7709
7710         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
7711
7712         for (i = 1; i < max_q_idx; i++)
7713         {
7714                 if ((quest[i].status == QUEST_STATUS_TAKEN) ||
7715                         ((quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER)) ||
7716                         (quest[i].status == QUEST_STATUS_COMPLETED))
7717                 {
7718                         /* Set the quest number temporary */
7719                         IDX old_quest = p_ptr->inside_quest;
7720                         int j;
7721
7722                         /* Clear the text */
7723                         for (j = 0; j < 10; j++) quest_text[j][0] = '\0';
7724                         quest_text_line = 0;
7725
7726                         p_ptr->inside_quest = i;
7727
7728                         /* Get the quest text */
7729                         init_flags = INIT_SHOW_TEXT;
7730
7731                         process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7732
7733                         /* Reset the old quest number */
7734                         p_ptr->inside_quest = old_quest;
7735
7736                         /* No info from "silent" quests */
7737                         if (quest[i].flags & QUEST_FLAG_SILENT) continue;
7738
7739                         total++;
7740
7741                         if (quest[i].type != QUEST_TYPE_RANDOM)
7742                         {
7743                                 char note[80] = "\0";
7744
7745                                 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
7746                                 {
7747                                         switch (quest[i].type)
7748                                         {
7749                                         case QUEST_TYPE_KILL_LEVEL:
7750                                         case QUEST_TYPE_KILL_ANY_LEVEL:
7751                                                 r_ptr = &r_info[quest[i].r_idx];
7752                                                 strcpy(name, r_name + r_ptr->name);
7753                                                 if (quest[i].max_num > 1)
7754                                                 {
7755 #ifdef JP
7756                                                         sprintf(note," - %d 体の%sを倒す。(あと %d 体)",
7757                                                                 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7758 #else
7759                                                         plural_aux(name);
7760                                                         sprintf(note," - kill %d %s, have killed %d.",
7761                                                                 (int)quest[i].max_num, name, (int)quest[i].cur_num);
7762 #endif
7763                                                 }
7764                                                 else
7765                                                         sprintf(note,_(" - %sを倒す。", " - kill %s."),name);
7766                                                 break;
7767
7768                                         case QUEST_TYPE_FIND_ARTIFACT:
7769                                                 if (quest[i].k_idx)
7770                                                 {
7771                                                         artifact_type *a_ptr = &a_info[quest[i].k_idx];
7772                                                         object_type forge;
7773                                                         object_type *q_ptr = &forge;
7774                                                         KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
7775                                                         object_prep(q_ptr, k_idx);
7776                                                         q_ptr->name1 = quest[i].k_idx;
7777                                                         q_ptr->ident = IDENT_STORE;
7778                                                         object_desc(name, q_ptr, OD_NAME_ONLY);
7779                                                 }
7780                                                 sprintf(note,_("\n   - %sを見つけ出す。", "\n   - Find out %s."), name);
7781                                                 break;
7782                                         case QUEST_TYPE_FIND_EXIT:
7783                                                 sprintf(note,_(" - 出口に到達する。", " - Reach to Exit."));
7784                                                 break;
7785
7786                                         case QUEST_TYPE_KILL_NUMBER:
7787 #ifdef JP
7788                                                 sprintf(note," - %d 体のモンスターを倒す。(あと %d 体)",
7789                                                         (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
7790 #else
7791                                                 sprintf(note," - Kill %d monsters, have killed %d.",
7792                                                         (int)quest[i].max_num, (int)quest[i].cur_num);
7793 #endif
7794                                                 break;
7795
7796                                         case QUEST_TYPE_KILL_ALL:
7797                                         case QUEST_TYPE_TOWER:
7798                                                 sprintf(note,_(" - 全てのモンスターを倒す。", " - Kill all monsters."));
7799                                                 break;
7800                                         }
7801                                 }
7802
7803                                 /* Print the quest info */
7804                                 sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
7805                                         quest[i].name, (int)quest[i].level, note);
7806
7807                                 fputs(tmp_str, fff);
7808
7809                                 if (quest[i].status == QUEST_STATUS_COMPLETED)
7810                                 {
7811                                         sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
7812                                         fputs(tmp_str, fff);
7813                                 }
7814                                 else
7815                                 {
7816                                         j = 0;
7817
7818                                         while (quest_text[j][0] && j < 10)
7819                                         {
7820                                                 fprintf(fff, "    %s\n", quest_text[j]);
7821                                                 j++;
7822                                         }
7823                                 }
7824                         }
7825                         else if (quest[i].level < rand_level) /* QUEST_TYPE_RANDOM */
7826                         {
7827                                 /* New random */
7828                                 rand_level = quest[i].level;
7829
7830                                 if (max_dlv[DUNGEON_ANGBAND] >= rand_level)
7831                                 {
7832                                         /* Print the quest info */
7833                                         r_ptr = &r_info[quest[i].r_idx];
7834                                         strcpy(name, r_name + r_ptr->name);
7835
7836                                         if (quest[i].max_num > 1)
7837                                         {
7838 #ifdef JP
7839                                                 sprintf(rand_tmp_str,"  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
7840                                                         quest[i].name, (int)quest[i].level,
7841                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7842 #else
7843                                                 plural_aux(name);
7844
7845                                                 sprintf(rand_tmp_str,"  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
7846                                                         quest[i].name, (int)quest[i].level,
7847                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
7848 #endif
7849                                         }
7850                                         else
7851                                         {
7852                                                 sprintf(rand_tmp_str,_("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
7853                                                         quest[i].name, (int)quest[i].level, name);
7854                                         }
7855                                 }
7856                         }
7857                 }
7858         }
7859
7860         /* Print the current random quest  */
7861         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
7862
7863         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7864 }
7865
7866
7867 static bool do_cmd_knowledge_quests_aux(FILE *fff, IDX q_idx)
7868 {
7869         char tmp_str[120];
7870         char playtime_str[16];
7871         quest_type* const q_ptr = &quest[q_idx];
7872
7873         if (is_fixed_quest_idx(q_idx))
7874         {
7875                 /* Set the quest number temporary */
7876                 IDX old_quest = p_ptr->inside_quest;
7877
7878                 p_ptr->inside_quest = q_idx;
7879
7880                 /* Get the quest */
7881                 init_flags = INIT_NAME_ONLY;
7882
7883                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7884
7885                 /* Reset the old quest number */
7886                 p_ptr->inside_quest = old_quest;
7887
7888                 /* No info from "silent" quests */
7889                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
7890         }
7891
7892         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
7893                 q_ptr->comptime/(60*60), (q_ptr->comptime/60)%60, q_ptr->comptime%60);
7894
7895         if (!is_fixed_quest_idx(q_idx) && q_ptr->r_idx)
7896         {
7897                 /* Print the quest info */
7898                 if (q_ptr->complev == 0)
7899                 {
7900                         sprintf(tmp_str,
7901                                 _("  %-35s (%3d階)            -   不戦勝 - %s\n",
7902                                   "  %-35s (Dungeon level: %3d) - Unearned - %s\n") ,
7903                                 r_name+r_info[q_ptr->r_idx].name,
7904                                 (int)q_ptr->level, playtime_str);
7905                 }
7906                 else
7907                 {
7908                         sprintf(tmp_str,
7909                                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
7910                                   "  %-35s (Dungeon level: %3d) - level %2d - %s\n") ,
7911                                 r_name+r_info[q_ptr->r_idx].name,
7912                                 (int)q_ptr->level,
7913                                 q_ptr->complev,
7914                                 playtime_str);
7915                 }
7916         }
7917         else
7918         {
7919                 /* Print the quest info */
7920                 sprintf(tmp_str,
7921                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
7922                           "  %-35s (Danger  level: %3d) - level %2d - %s\n") ,
7923                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
7924         }
7925
7926         fputs(tmp_str, fff);
7927
7928         return TRUE;
7929 }
7930
7931 /*
7932  * Print all finished quests
7933  */
7934 void do_cmd_knowledge_quests_completed(FILE *fff, IDX quest_num[])
7935 {
7936         int i;
7937         int total = 0;
7938
7939         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
7940         for (i = 1; i < max_q_idx; i++)
7941         {
7942                 IDX q_idx = quest_num[i];
7943                 quest_type* const q_ptr = &quest[q_idx];
7944
7945                 if (q_ptr->status == QUEST_STATUS_FINISHED &&
7946                     do_cmd_knowledge_quests_aux(fff, q_idx))
7947                 {
7948                         ++ total;
7949                 }
7950         }
7951         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7952 }
7953
7954
7955 /*
7956  * Print all failed quests
7957  */
7958 void do_cmd_knowledge_quests_failed(FILE *fff, IDX quest_num[])
7959 {
7960         IDX i;
7961         int total = 0;
7962
7963         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
7964         for (i = 1; i < max_q_idx; i++)
7965         {
7966                 IDX q_idx = quest_num[i];
7967                 quest_type* const q_ptr = &quest[q_idx];
7968
7969                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
7970                     do_cmd_knowledge_quests_aux(fff, q_idx))
7971                 {
7972                         ++ total;
7973                 }
7974         }
7975         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7976 }
7977
7978
7979 /*
7980  * Print all random quests
7981  */
7982 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
7983 {
7984         char tmp_str[120];
7985         int i;
7986         int total = 0;
7987
7988         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
7989         for (i = 1; i < max_q_idx; i++)
7990         {
7991                 /* No info from "silent" quests */
7992                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
7993
7994                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
7995                 {
7996                         total++;
7997
7998                         /* Print the quest info */
7999                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
8000                                 quest[i].name, (int)quest[i].level, r_name+r_info[quest[i].r_idx].name);
8001                         fputs(tmp_str, fff);
8002                 }
8003         }
8004         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8005 }
8006
8007
8008 bool ang_sort_comp_quest_num(vptr u, vptr v, int a, int b)
8009 {
8010         QUEST_IDX *q_num = (QUEST_IDX *)u;
8011         quest_type *qa = &quest[q_num[a]];
8012         quest_type *qb = &quest[q_num[b]];
8013
8014         /* Unused */
8015         (void)v;
8016
8017         return (qa->comptime != qb->comptime) ?
8018                 (qa->comptime < qb->comptime) :
8019                 (qa->level <= qb->level);
8020 }
8021
8022 void ang_sort_swap_quest_num(vptr u, vptr v, int a, int b)
8023 {
8024         QUEST_IDX *q_num = (QUEST_IDX *)u;
8025         QUEST_IDX tmp;
8026
8027         /* Unused */
8028         (void)v;
8029
8030         tmp = q_num[a];
8031         q_num[a] = q_num[b];
8032         q_num[b] = tmp;
8033 }
8034
8035
8036 /*
8037  * Print quest status of all active quests
8038  */
8039 static void do_cmd_knowledge_quests(void)
8040 {
8041         FILE *fff;
8042         GAME_TEXT file_name[1024];
8043         IDX *quest_num;
8044         int dummy;
8045         IDX i;
8046
8047         /* Open a new file */
8048         fff = my_fopen_temp(file_name, 1024);
8049         if (!fff)
8050         {
8051             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8052             msg_print(NULL);
8053             return;
8054         }
8055
8056         /* Allocate Memory */
8057         C_MAKE(quest_num, max_q_idx, IDX);
8058
8059         /* Sort by compete level */
8060         for (i = 1; i < max_q_idx; i++) quest_num[i] = i;
8061         ang_sort_comp = ang_sort_comp_quest_num;
8062         ang_sort_swap = ang_sort_swap_quest_num;
8063         ang_sort(quest_num, &dummy, max_q_idx);
8064
8065         /* Dump Quest Information */
8066         do_cmd_knowledge_quests_current(fff);
8067         fputc('\n', fff);
8068         do_cmd_knowledge_quests_completed(fff, quest_num);
8069         fputc('\n', fff);
8070         do_cmd_knowledge_quests_failed(fff, quest_num);
8071         if (p_ptr->wizard)
8072         {
8073                 fputc('\n', fff);
8074                 do_cmd_knowledge_quests_wiz_random(fff);
8075         }
8076         my_fclose(fff);
8077
8078         /* Display the file contents */
8079         show_file(TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
8080
8081         /* Remove the file */
8082         fd_kill(file_name);
8083
8084         /* Free Memory */
8085         C_KILL(quest_num, max_q_idx, IDX);
8086 }
8087
8088
8089 /*
8090  * List my home
8091  */
8092 static void do_cmd_knowledge_home(void)
8093 {
8094         FILE *fff;
8095
8096         int i;
8097         GAME_TEXT file_name[1024];
8098         store_type  *st_ptr;
8099         GAME_TEXT o_name[MAX_NLEN];
8100         cptr            paren = ")";
8101
8102         process_dungeon_file("w_info.txt", 0, 0, max_wild_y, max_wild_x);
8103
8104         /* Open a new file */
8105         fff = my_fopen_temp(file_name, 1024);
8106         if (!fff) {
8107                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8108                 msg_print(NULL);
8109                 return;
8110         }
8111
8112         if (fff)
8113         {
8114                 /* Print all homes in the different towns */
8115                 st_ptr = &town[1].store[STORE_HOME];
8116
8117                 /* Home -- if anything there */
8118                 if (st_ptr->stock_num)
8119                 {
8120 #ifdef JP
8121                         TERM_LEN x = 1;
8122 #endif
8123                         /* Header with name of the town */
8124                         fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
8125
8126                         /* Dump all available items */
8127                         for (i = 0; i < st_ptr->stock_num; i++)
8128                         {
8129 #ifdef JP
8130                                 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
8131                                 object_desc(o_name, &st_ptr->stock[i], 0);
8132                                 if (strlen(o_name) <= 80-3)
8133                                 {
8134                                         fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8135                                 }
8136                                 else
8137                                 {
8138                                         int n;
8139                                         char *t;
8140                                         for (n = 0, t = o_name; n < 80-3; n++, t++)
8141                                                 if(iskanji(*t)) {t++; n++;}
8142                                         if (n == 81-3) n = 79-3; /* 最後が漢字半分 */
8143
8144                                         fprintf(fff, "%c%s %.*s\n", I2A(i%12), paren, n, o_name);
8145                                         fprintf(fff, "   %.77s\n", o_name+n);
8146                                 }
8147 #else
8148                                 object_desc(o_name, &st_ptr->stock[i], 0);
8149                                 fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8150 #endif
8151
8152                         }
8153
8154                         /* Add an empty line */
8155                         fprintf(fff, "\n\n");
8156                 }
8157         }
8158         my_fclose(fff);
8159
8160         /* Display the file contents */
8161         show_file(TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
8162
8163         /* Remove the file */
8164         fd_kill(file_name);
8165 }
8166
8167
8168 /*
8169  * Check the status of "autopick"
8170  */
8171 static void do_cmd_knowledge_autopick(void)
8172 {
8173         int k;
8174         FILE *fff;
8175         GAME_TEXT file_name[1024];
8176
8177         /* Open a new file */
8178         fff = my_fopen_temp(file_name, 1024);
8179
8180         if (!fff)
8181         {
8182             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8183             msg_print(NULL);
8184             return;
8185         }
8186
8187         if (!max_autopick)
8188         {
8189             fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
8190         }
8191         else
8192         {
8193                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
8194                                            "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
8195         }
8196
8197         for (k = 0; k < max_autopick; k++)
8198         {
8199                 cptr tmp;
8200                 byte act = autopick_list[k].action;
8201                 if (act & DONT_AUTOPICK)
8202                 {
8203                         tmp = _("放置", "Leave");
8204                 }
8205                 else if (act & DO_AUTODESTROY)
8206                 {
8207                         tmp = _("破壊", "Destroy");
8208                 }
8209                 else if (act & DO_AUTOPICK)
8210                 {
8211                         tmp = _("拾う", "Pickup");
8212                 }
8213                 else
8214                 {
8215                         tmp = _("確認", "Query");
8216                 }
8217
8218                 if (act & DO_DISPLAY)
8219                         fprintf(fff, "%11s", format("[%s]", tmp));
8220                 else
8221                         fprintf(fff, "%11s", format("(%s)", tmp));
8222
8223                 tmp = autopick_line_from_entry(&autopick_list[k]);
8224                 fprintf(fff, " %s", tmp);
8225                 string_free(tmp);
8226                 fprintf(fff, "\n");
8227         }
8228         my_fclose(fff);
8229         /* Display the file contents */
8230         show_file(TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
8231
8232         /* Remove the file */
8233         fd_kill(file_name);
8234 }
8235
8236
8237 /*
8238  * Interact with "knowledge"
8239  */
8240 void do_cmd_knowledge(void)
8241 {
8242         int i, p = 0;
8243         bool need_redraw = FALSE;
8244
8245         /* File type is "TEXT" */
8246         FILE_TYPE(FILE_TYPE_TEXT);
8247         screen_save();
8248
8249         /* Interact until done */
8250         while (1)
8251         {
8252                 Term_clear();
8253
8254                 /* Ask for a choice */
8255                 prt(format(_("%d/2 ページ", "page %d/2"), (p+1)), 2, 65);
8256                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
8257
8258                 /* Give some choices */
8259 #ifdef JP
8260                 if (p == 0)
8261                 {
8262                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
8263                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
8264                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
8265                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
8266                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
8267                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
8268                         prt("(7) 現在のペット                         の一覧", 12, 5);
8269                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
8270                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
8271                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
8272                 }
8273                 else
8274                 {
8275                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
8276                         prt("(b) 突然変異                             の一覧", 7, 5);
8277                         prt("(c) 武器の経験値                         の一覧", 8, 5);
8278                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
8279                         prt("(e) 技能の経験値                         の一覧", 10, 5);
8280                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
8281                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
8282                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
8283                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
8284                 }
8285 #else
8286                 if (p == 0)
8287                 {
8288                         prt("(1) Display known artifacts", 6, 5);
8289                         prt("(2) Display known objects", 7, 5);
8290                         prt("(3) Display remaining uniques", 8, 5);
8291                         prt("(4) Display known monster", 9, 5);
8292                         prt("(5) Display kill count", 10, 5);
8293                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
8294                         prt("(7) Display current pets", 12, 5);
8295                         prt("(8) Display home inventory", 13, 5);
8296                         prt("(9) Display *identified* equip.", 14, 5);
8297                         prt("(0) Display terrain symbols.", 15, 5);
8298                 }
8299                 else
8300                 {
8301                         prt("(a) Display about yourself", 6, 5);
8302                         prt("(b) Display mutations", 7, 5);
8303                         prt("(c) Display weapon proficiency", 8, 5);
8304                         prt("(d) Display spell proficiency", 9, 5);
8305                         prt("(e) Display misc. proficiency", 10, 5);
8306                         prt("(f) Display virtues", 11, 5);
8307                         prt("(g) Display dungeons", 12, 5);
8308                         prt("(h) Display current quests", 13, 5);
8309                         prt("(i) Display auto pick/destroy", 14, 5);
8310                 }
8311 #endif
8312                 /* Prompt */
8313                 prt(_("-続く-", "-more-"), 17, 8);
8314                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
8315                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
8316                 /*prt("-) 前ページ", 21, 60);*/
8317                 prt(_("コマンド:", "Command: "), 20, 0);
8318                 i = inkey();
8319
8320                 if (i == ESCAPE) break;
8321                 switch (i)
8322                 {
8323                 case ' ': /* Page change */
8324                 case '-':
8325                         p = 1 - p;
8326                         break;
8327                 case '1': /* Artifacts */
8328                         do_cmd_knowledge_artifacts();
8329                         break;
8330                 case '2': /* Objects */
8331                         do_cmd_knowledge_objects(&need_redraw, FALSE, -1);
8332                         break;
8333                 case '3': /* Uniques */
8334                         do_cmd_knowledge_uniques();
8335                         break;
8336                 case '4': /* Monsters */
8337                         do_cmd_knowledge_monsters(&need_redraw, FALSE, -1);
8338                         break;
8339                 case '5': /* Kill count  */
8340                         do_cmd_knowledge_kill_count();
8341                         break;
8342                 case '6': /* wanted */
8343                         if (!vanilla_town) do_cmd_knowledge_kubi();
8344                         break;
8345                 case '7': /* Pets */
8346                         do_cmd_knowledge_pets();
8347                         break;
8348                 case '8': /* Home */
8349                         do_cmd_knowledge_home();
8350                         break;
8351                 case '9': /* Resist list */
8352                         do_cmd_knowledge_inven();
8353                         break;
8354                 case '0': /* Feature list */
8355                         {
8356                                 IDX lighting_level = F_LIT_STANDARD;
8357                                 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
8358                         }
8359                         break;
8360                 /* Next page */
8361                 case 'a': /* Max stat */
8362                         do_cmd_knowledge_stat();
8363                         break;
8364                 case 'b': /* Mutations */
8365                         do_cmd_knowledge_mutations();
8366                         break;
8367                 case 'c': /* weapon-exp */
8368                         do_cmd_knowledge_weapon_exp();
8369                         break;
8370                 case 'd': /* spell-exp */
8371                         do_cmd_knowledge_spell_exp();
8372                         break;
8373                 case 'e': /* skill-exp */
8374                         do_cmd_knowledge_skill_exp();
8375                         break;
8376                 case 'f': /* Virtues */
8377                         do_cmd_knowledge_virtues();
8378                         break;
8379                 case 'g': /* Dungeon */
8380                         do_cmd_knowledge_dungeon();
8381                         break;
8382                 case 'h': /* Quests */
8383                         do_cmd_knowledge_quests();
8384                         break;
8385                 case 'i': /* Autopick */
8386                         do_cmd_knowledge_autopick();
8387                         break;
8388                 default: /* Unknown option */
8389                         bell();
8390                 }
8391
8392                 msg_erase();
8393         }
8394         screen_load();
8395
8396         if (need_redraw) do_cmd_redraw();
8397 }
8398
8399
8400 /*
8401  * Check on the status of an active quest
8402  */
8403 void do_cmd_checkquest(void)
8404 {
8405         /* File type is "TEXT" */
8406         FILE_TYPE(FILE_TYPE_TEXT);
8407         screen_save();
8408
8409         /* Quest info */
8410         do_cmd_knowledge_quests();
8411         screen_load();
8412 }
8413
8414
8415 /*
8416  * Display the time and date
8417  */
8418 void do_cmd_time(void)
8419 {
8420         int day, hour, min, full, start, end, num;
8421         char desc[1024];
8422
8423         char buf[1024];
8424         char day_buf[10];
8425
8426         FILE *fff;
8427
8428         extract_day_hour_min(&day, &hour, &min);
8429
8430         full = hour * 100 + min;
8431
8432         start = 9999;
8433         end = -9999;
8434
8435         num = 0;
8436
8437         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
8438
8439         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
8440         else strcpy(day_buf, "*****");
8441
8442 #ifdef JP
8443         msg_format("%s日目, 時刻は%d:%02d %sです。",
8444                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8445                    min, (hour < 12) ? "AM" : "PM");
8446 #else
8447         msg_format("This is day %s. The time is %d:%02d %s.",
8448                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8449                    min, (hour < 12) ? "AM" : "PM");
8450 #endif
8451
8452
8453         /* Find the path */
8454         if (!randint0(10) || p_ptr->image)
8455         {
8456                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
8457         }
8458         else
8459         {
8460                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
8461         }
8462
8463         /* Open this file */
8464         fff = my_fopen(buf, "rt");
8465
8466         if (!fff) return;
8467
8468         /* Find this time */
8469         while (!my_fgets(fff, buf, sizeof(buf)))
8470         {
8471                 /* Ignore comments */
8472                 if (!buf[0] || (buf[0] == '#')) continue;
8473
8474                 /* Ignore invalid lines */
8475                 if (buf[1] != ':') continue;
8476
8477                 /* Process 'Start' */
8478                 if (buf[0] == 'S')
8479                 {
8480                         /* Extract the starting time */
8481                         start = atoi(buf + 2);
8482
8483                         /* Assume valid for an hour */
8484                         end = start + 59;
8485
8486                         /* Next... */
8487                         continue;
8488                 }
8489
8490                 /* Process 'End' */
8491                 if (buf[0] == 'E')
8492                 {
8493                         /* Extract the ending time */
8494                         end = atoi(buf + 2);
8495
8496                         /* Next... */
8497                         continue;
8498                 }
8499
8500                 /* Ignore incorrect range */
8501                 if ((start > full) || (full > end)) continue;
8502
8503                 /* Process 'Description' */
8504                 if (buf[0] == 'D')
8505                 {
8506                         num++;
8507
8508                         /* Apply the randomizer */
8509                         if (!randint0(num)) strcpy(desc, buf + 2);
8510
8511                         /* Next... */
8512                         continue;
8513                 }
8514         }
8515
8516         msg_print(desc);
8517         my_fclose(fff);
8518 }