OSDN Git Service

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