OSDN Git Service

435d206aed03e89bb8aa01d6451abf6a56d5fa8c
[hengband/hengband.git] / src / cmd / cmd-dump.c
1 /*!
2  * @file cmd-dump.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  * The dump commands of original Angband simply add new lines to
16  * existing files; these files will become bigger and bigger unless
17  * an user deletes some or all of these files by hand at some
18  * point.
19  * These three functions automatically delete old dumped lines
20  * before adding new ones.  Since there are various kinds of automatic
21  * dumps in a single file, we add a header and a footer with a type
22  * name for every automatic dump, and kill old lines only when the
23  * lines have the correct type of header and footer.
24  * We need to be quite paranoid about correctness; the user might
25  * (mistakenly) edit the file by hand, and see all their work come
26  * to nothing on the next auto dump otherwise.  The current code only
27  * detects changes by noting inconsistencies between the actual number
28  * of lines and the number written in the footer.  Note that this will
29  * not catch single-line edits.
30  * </pre>
31  */
32
33 #include "angband.h"
34 #include "cmd/cmd-draw.h"
35 #include "cmd/cmd-dump.h"
36 #include "cmd/cmd-inventory.h"
37 #include "cmd/lighting-level-table.h"
38 #include "cmd/cmd-visuals.h"
39 #include "cmd/dump-util.h"
40 #include "gameterm.h"
41 #include "core.h" // 暫定。後で消す.
42 #include "core/show-file.h"
43 #include "io/read-pref-file.h"
44 #include "io/interpret-pref-file.h"
45
46 #include "knowledge/knowledge-items.h"
47 #include "knowledge/knowledge-experiences.h"
48 #include "knowledge/knowledge-features.h"
49 #include "knowledge/knowledge-monsters.h"
50 #include "knowledge/knowledge-quests.h"
51 #include "knowledge/knowledge-self.h"
52 #include "knowledge/knowledge-uniques.h"
53
54 #include "autopick.h"
55 #include "dungeon.h"
56 #include "world.h"
57 #include "view/display-player.h" // 暫定。後で消す.
58 #include "player-personality.h"
59 #include "sort.h"
60 #include "mutation.h"
61 #include "quest.h"
62 #include "market/store.h"
63 #include "artifact.h"
64 #include "object-flavor.h"
65 #include "object/object-kind.h"
66 #include "floor-town.h"
67 #include "cmd/feeling-table.h"
68 #include "cmd/object-group-table.h"
69 #include "market/store-util.h"
70 #include "view-mainwindow.h" // 暫定。後で消す
71 #include "english.h"
72
73 #include "diary-subtitle-table.h"
74 #include "io/write-diary.h"
75 #include "chuukei.h"
76
77 /*!
78  * @brief prefファイルを選択して処理する /
79  * Ask for a "user pref line" and process it
80  * @brief prf出力内容を消去する /
81  * Remove old lines automatically generated before.
82  * @param orig_file 消去を行うファイル名
83  */
84 static void remove_auto_dump(concptr orig_file, concptr auto_dump_mark)
85 {
86         char buf[1024];
87         bool between_mark = FALSE;
88         bool changed = FALSE;
89         int line_num = 0;
90         long header_location = 0;
91         char header_mark_str[80];
92         char footer_mark_str[80];
93
94         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
95         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
96         size_t mark_len = strlen(footer_mark_str);
97
98         FILE *orig_fff;
99         orig_fff = my_fopen(orig_file, "r");
100         if (!orig_fff) return;
101
102         FILE *tmp_fff = NULL;
103         char tmp_file[FILE_NAME_SIZE];
104         if (!open_temporary_file(&tmp_fff, tmp_file)) return;
105
106         while (TRUE)
107         {
108                 if (my_fgets(orig_fff, buf, sizeof(buf)))
109                 {
110                         if (between_mark)
111                         {
112                                 fseek(orig_fff, header_location, SEEK_SET);
113                                 between_mark = FALSE;
114                                 continue;
115                         }
116                         else
117                         {
118                                 break;
119                         }
120                 }
121
122                 if (!between_mark)
123                 {
124                         if (!strcmp(buf, header_mark_str))
125                         {
126                                 header_location = ftell(orig_fff);
127                                 line_num = 0;
128                                 between_mark = TRUE;
129                                 changed = TRUE;
130                         }
131                         else
132                         {
133                                 fprintf(tmp_fff, "%s\n", buf);
134                         }
135
136                         continue;
137                 }
138
139                 if (!strncmp(buf, footer_mark_str, mark_len))
140                 {
141                         int tmp;
142                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
143                                 || tmp != line_num)
144                         {
145                                 fseek(orig_fff, header_location, SEEK_SET);
146                         }
147
148                         between_mark = FALSE;
149                         continue;
150                 }
151
152                 line_num++;
153         }
154
155         my_fclose(orig_fff);
156         my_fclose(tmp_fff);
157
158         if (changed)
159         {
160                 tmp_fff = my_fopen(tmp_file, "r");
161                 orig_fff = my_fopen(orig_file, "w");
162                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
163                         fprintf(orig_fff, "%s\n", buf);
164
165                 my_fclose(orig_fff);
166                 my_fclose(tmp_fff);
167         }
168
169         fd_kill(tmp_file);
170 }
171
172
173 #ifdef JP
174 #else
175 /*!
176  * @brief Return suffix of ordinal number
177  * @param num number
178  * @return pointer of suffix string.
179  */
180 concptr get_ordinal_number_suffix(int num)
181 {
182         num = ABS(num) % 100;
183         switch (num % 10)
184         {
185         case 1:
186                 return (num == 11) ? "th" : "st";
187         case 2:
188                 return (num == 12) ? "th" : "nd";
189         case 3:
190                 return (num == 13) ? "th" : "rd";
191         default:
192                 return "th";
193         }
194 }
195 #endif
196
197 /*!
198  * @brief 画面を再描画するコマンドのメインルーチン
199  * Hack -- redraw the screen
200  * @param creature_ptr プレーヤーへの参照ポインタ
201  * @return なし
202  * @details
203  * Allow absolute file names?
204  */
205 void do_cmd_pref(player_type *creature_ptr)
206 {
207         char buf[80];
208         strcpy(buf, "");
209         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
210
211         (void)interpret_pref_file(creature_ptr, buf);
212 }
213
214
215 /*!
216  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
217  * @param creature_ptr プレーヤーへの参照ポインタ
218  * @return なし
219  */
220 void do_cmd_reload_autopick(player_type *creature_ptr)
221 {
222         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
223                 return;
224
225         autopick_load_pref(creature_ptr, TRUE);
226 }
227
228
229 /*
230  * Interact with "colors"
231  */
232 void do_cmd_colors(player_type *creature_ptr)
233 {
234         int i;
235         char tmp[160];
236         char buf[1024];
237         FILE *auto_dump_stream;
238         FILE_TYPE(FILE_TYPE_TEXT);
239         screen_save();
240         while (TRUE)
241         {
242                 Term_clear();
243                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
244                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
245                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
246                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
247                 prt(_("コマンド: ", "Command: "), 8, 0);
248                 i = inkey();
249                 if (i == ESCAPE) break;
250
251                 if (i == '1')
252                 {
253                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
254                         prt(_("ファイル: ", "File: "), 10, 0);
255                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
256                         if (!askfor(tmp, 70)) continue;
257
258                         (void)process_pref_file(creature_ptr, tmp);
259                         Term_xtra(TERM_XTRA_REACT, 0);
260                         Term_redraw();
261                 }
262                 else if (i == '2')
263                 {
264                         static concptr mark = "Colors";
265                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
266                         prt(_("ファイル: ", "File: "), 10, 0);
267                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
268                         if (!askfor(tmp, 70)) continue;
269
270                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
271                         if (!open_auto_dump(&auto_dump_stream, buf, mark)) continue;
272
273                         auto_dump_printf(auto_dump_stream, _("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
274                         for (i = 0; i < 256; i++)
275                         {
276                                 int kv = angband_color_table[i][0];
277                                 int rv = angband_color_table[i][1];
278                                 int gv = angband_color_table[i][2];
279                                 int bv = angband_color_table[i][3];
280
281                                 concptr name = _("未知", "unknown");
282                                 if (!kv && !rv && !gv && !bv) continue;
283
284                                 if (i < 16) name = color_names[i];
285
286                                 auto_dump_printf(auto_dump_stream, _("# カラー '%s'\n", "# Color '%s'\n"), name);
287                                 auto_dump_printf(auto_dump_stream, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
288                                         i, kv, rv, gv, bv);
289                         }
290
291                         close_auto_dump(&auto_dump_stream, mark);
292                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
293                 }
294                 else if (i == '3')
295                 {
296                         static byte a = 0;
297                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
298                         while (TRUE)
299                         {
300                                 concptr name;
301                                 clear_from(10);
302                                 for (byte j = 0; j < 16; j++)
303                                 {
304                                         Term_putstr(j * 4, 20, -1, a, "###");
305                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
306                                 }
307
308                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
309                                 Term_putstr(5, 10, -1, TERM_WHITE,
310                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
311                                 Term_putstr(5, 12, -1, TERM_WHITE,
312                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
313                                                 angband_color_table[a][0],
314                                                 angband_color_table[a][1],
315                                                 angband_color_table[a][2],
316                                                 angband_color_table[a][3]));
317                                 Term_putstr(0, 14, -1, TERM_WHITE,
318                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
319                                 i = inkey();
320                                 if (i == ESCAPE) break;
321
322                                 if (i == 'n') a = (byte)(a + 1);
323                                 if (i == 'N') a = (byte)(a - 1);
324                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
325                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
326                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
327                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
328                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
329                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
330                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
331                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
332
333                                 Term_xtra(TERM_XTRA_REACT, 0);
334                                 Term_redraw();
335                         }
336                 }
337                 else
338                 {
339                         bell();
340                 }
341
342                 msg_erase();
343         }
344
345         screen_load();
346 }
347
348
349 /*
350  * Note something in the message recall
351  */
352 void do_cmd_note(void)
353 {
354         char buf[80];
355         strcpy(buf, "");
356         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
357         if (!buf[0] || (buf[0] == ' ')) return;
358
359         msg_format(_("メモ: %s", "Note: %s"), buf);
360 }
361
362
363 /*
364  * Mention the current version
365  */
366 void do_cmd_version(void)
367 {
368 #if FAKE_VER_EXTRA > 0
369         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
370                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
371 #else
372         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
373                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
374 #endif
375 }
376
377
378 /*
379  * Note that "feeling" is set to zero unless some time has passed.
380  * Note that this is done when the level is GENERATED, not entered.
381  */
382 void do_cmd_feeling(player_type *creature_ptr)
383 {
384         if (creature_ptr->wild_mode) return;
385
386         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
387         {
388                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
389                 return;
390         }
391
392         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
393         {
394                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
395                 {
396                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
397                         return;
398                 }
399
400                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
401                 return;
402         }
403
404         if (!creature_ptr->current_floor_ptr->dun_level)
405         {
406                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
407                 return;
408         }
409
410         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
411                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
412         else if (IS_ECHIZEN(creature_ptr))
413                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
414         else
415                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
416 }
417
418
419 /*
420  * Check the status of "autopick"
421  */
422 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
423 {
424         FILE *fff = NULL;
425         GAME_TEXT file_name[FILE_NAME_SIZE];
426         if (!open_temporary_file(&fff, file_name)) return;
427
428         if (!max_autopick)
429         {
430                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
431         }
432         else
433         {
434                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
435                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
436         }
437
438         for (int k = 0; k < max_autopick; k++)
439         {
440                 concptr tmp;
441                 byte act = autopick_list[k].action;
442                 if (act & DONT_AUTOPICK)
443                 {
444                         tmp = _("放置", "Leave");
445                 }
446                 else if (act & DO_AUTODESTROY)
447                 {
448                         tmp = _("破壊", "Destroy");
449                 }
450                 else if (act & DO_AUTOPICK)
451                 {
452                         tmp = _("拾う", "Pickup");
453                 }
454                 else
455                 {
456                         tmp = _("確認", "Query");
457                 }
458
459                 if (act & DO_DISPLAY)
460                         fprintf(fff, "%11s", format("[%s]", tmp));
461                 else
462                         fprintf(fff, "%11s", format("(%s)", tmp));
463
464                 tmp = autopick_line_from_entry(&autopick_list[k]);
465                 fprintf(fff, " %s", tmp);
466                 string_free(tmp);
467                 fprintf(fff, "\n");
468         }
469
470         my_fclose(fff);
471
472         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
473         fd_kill(file_name);
474 }
475
476
477 /*
478  * Interact with "knowledge"
479  */
480 void do_cmd_knowledge(player_type *creature_ptr)
481 {
482         int i, p = 0;
483         bool need_redraw = FALSE;
484         FILE_TYPE(FILE_TYPE_TEXT);
485         screen_save();
486         while (TRUE)
487         {
488                 Term_clear();
489                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
490                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
491                 if (p == 0)
492                 {
493                         prt(_("(1) 既知の伝説のアイテム                 の一覧", "(1) Display known artifacts"), 6, 5);
494                         prt(_("(2) 既知のアイテム                       の一覧", "(2) Display known objects"), 7, 5);
495                         prt(_("(3) 既知の生きているユニーク・モンスター の一覧", "(3) Display remaining uniques"), 8, 5);
496                         prt(_("(4) 既知のモンスター                     の一覧", "(4) Display known monster"), 9, 5);
497                         prt(_("(5) 倒した敵の数                         の一覧", "(5) Display kill count"), 10, 5);
498                         if (!vanilla_town) prt(_("(6) 賞金首                               の一覧", "(6) Display wanted monsters"), 11, 5);
499                         prt(_("(7) 現在のペット                         の一覧", "(7) Display current pets"), 12, 5);
500                         prt(_("(8) 我が家のアイテム                     の一覧", "(8) Display home inventory"), 13, 5);
501                         prt(_("(9) *鑑定*済み装備の耐性                 の一覧", "(9) Display *identified* equip."), 14, 5);
502                         prt(_("(0) 地形の表示文字/タイル                の一覧", "(0) Display terrain symbols."), 15, 5);
503                 }
504                 else
505                 {
506                         prt(_("(a) 自分に関する情報                     の一覧", "(a) Display about yourself"), 6, 5);
507                         prt(_("(b) 突然変異                             の一覧", "(b) Display mutations"), 7, 5);
508                         prt(_("(c) 武器の経験値                         の一覧", "(c) Display weapon proficiency"), 8, 5);
509                         prt(_("(d) 魔法の経験値                         の一覧", "(d) Display spell proficiency"), 9, 5);
510                         prt(_("(e) 技能の経験値                         の一覧", "(e) Display misc. proficiency"), 10, 5);
511                         prt(_("(f) プレイヤーの徳                       の一覧", "(f) Display virtues"), 11, 5);
512                         prt(_("(g) 入ったダンジョン                     の一覧", "(g) Display dungeons"), 12, 5);
513                         prt(_("(h) 実行中のクエスト                     の一覧", "(h) Display current quests"), 13, 5);
514                         prt(_("(i) 現在の自動拾い/破壊設定              の一覧", "(i) Display auto pick/destroy"), 14, 5);
515                 }
516
517                 prt(_("-続く-", "-more-"), 17, 8);
518                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
519                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
520                 prt(_("コマンド:", "Command: "), 20, 0);
521                 i = inkey();
522
523                 if (i == ESCAPE) break;
524                 switch (i)
525                 {
526                 case ' ': /* Page change */
527                 case '-':
528                         p = 1 - p;
529                         break;
530                 case '1': /* Artifacts */
531                         do_cmd_knowledge_artifacts(creature_ptr);
532                         break;
533                 case '2': /* Objects */
534                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
535                         break;
536                 case '3': /* Uniques */
537                         do_cmd_knowledge_uniques(creature_ptr);
538                         break;
539                 case '4': /* Monsters */
540                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
541                         break;
542                 case '5': /* Kill count  */
543                         do_cmd_knowledge_kill_count(creature_ptr);
544                         break;
545                 case '6': /* wanted */
546                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
547                         break;
548                 case '7': /* Pets */
549                         do_cmd_knowledge_pets(creature_ptr);
550                         break;
551                 case '8': /* Home */
552                         do_cmd_knowledge_home(creature_ptr);
553                         break;
554                 case '9': /* Resist list */
555                         do_cmd_knowledge_inventory(creature_ptr);
556                         break;
557                 case '0': /* Feature list */
558                 {
559                         IDX lighting_level = F_LIT_STANDARD;
560                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
561                 }
562                 break;
563                 /* Next page */
564                 case 'a': /* Max stat */
565                         do_cmd_knowledge_stat(creature_ptr);
566                         break;
567                 case 'b': /* Mutations */
568                         do_cmd_knowledge_mutations(creature_ptr);
569                         break;
570                 case 'c': /* weapon-exp */
571                         do_cmd_knowledge_weapon_exp(creature_ptr);
572                         break;
573                 case 'd': /* spell-exp */
574                         do_cmd_knowledge_spell_exp(creature_ptr);
575                         break;
576                 case 'e': /* skill-exp */
577                         do_cmd_knowledge_skill_exp(creature_ptr);
578                         break;
579                 case 'f': /* Virtues */
580                         do_cmd_knowledge_virtues(creature_ptr);
581                         break;
582                 case 'g': /* Dungeon */
583                         do_cmd_knowledge_dungeon(creature_ptr);
584                         break;
585                 case 'h': /* Quests */
586                         do_cmd_knowledge_quests(creature_ptr);
587                         break;
588                 case 'i': /* Autopick */
589                         do_cmd_knowledge_autopick(creature_ptr);
590                         break;
591                 default: /* Unknown option */
592                         bell();
593                 }
594
595                 msg_erase();
596         }
597
598         screen_load();
599         if (need_redraw) do_cmd_redraw(creature_ptr);
600 }
601
602
603 /*
604  * Check on the status of an active quest
605  * @param creature_ptr プレーヤーへの参照ポインタ
606  * @return なし
607  */
608 void do_cmd_checkquest(player_type *creature_ptr)
609 {
610         FILE_TYPE(FILE_TYPE_TEXT);
611         screen_save();
612         do_cmd_knowledge_quests(creature_ptr);
613         screen_load();
614 }
615
616
617 /*
618  * Display the time and date
619  * @param creature_ptr プレーヤーへの参照ポインタ
620  * @return なし
621  */
622 void do_cmd_time(player_type *creature_ptr)
623 {
624         int day, hour, min;
625         extract_day_hour_min(creature_ptr, &day, &hour, &min);
626
627         char desc[1024];
628         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
629
630         char day_buf[10];
631         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
632         else strcpy(day_buf, "*****");
633
634         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
635                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
636
637         char buf[1024];
638         if (!randint0(10) || creature_ptr->image)
639         {
640                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
641         }
642         else
643         {
644                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
645         }
646
647         FILE *fff;
648         fff = my_fopen(buf, "rt");
649
650         if (!fff) return;
651
652         int full = hour * 100 + min;
653         int start = 9999;
654         int end = -9999;
655         int num = 0;
656         while (!my_fgets(fff, buf, sizeof(buf)))
657         {
658                 if (!buf[0] || (buf[0] == '#')) continue;
659                 if (buf[1] != ':') continue;
660
661                 if (buf[0] == 'S')
662                 {
663                         start = atoi(buf + 2);
664                         end = start + 59;
665                         continue;
666                 }
667
668                 if (buf[0] == 'E')
669                 {
670                         end = atoi(buf + 2);
671                         continue;
672                 }
673
674                 if ((start > full) || (full > end)) continue;
675
676                 if (buf[0] == 'D')
677                 {
678                         num++;
679                         if (!randint0(num)) strcpy(desc, buf + 2);
680
681                         continue;
682                 }
683         }
684
685         msg_print(desc);
686         my_fclose(fff);
687 }