OSDN Git Service

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