OSDN Git Service

[Refactor] #3230 PlayerType::update に関わる処理を、RedrawingFlagsUpdaterに集約した
[hengbandforosx/hengbandosx.git] / src / autopick / autopick-registry.cpp
1 /*!
2  * @brief 自動拾いにアイテムを登録する
3  * @date 2020/04/26
4  * @author Hourier
5  */
6
7 #include "autopick/autopick-registry.h"
8 #include "autopick/autopick-entry.h"
9 #include "autopick/autopick-finder.h"
10 #include "autopick/autopick-methods-table.h"
11 #include "autopick/autopick-reader-writer.h"
12 #include "autopick/autopick-util.h"
13 #include "core/asking-player.h"
14 #include "flavor/flavor-describer.h"
15 #include "io/files-util.h"
16 #include "object-enchant/item-feeling.h"
17 #include "object-enchant/special-object-flags.h"
18 #include "perception/object-perception.h"
19 #include "system/item-entity.h"
20 #include "system/player-type-definition.h"
21 #include "util/angband-files.h"
22 #include "view/display-messages.h"
23
24 static const char autoregister_header[] = "?:$AUTOREGISTER";
25
26 /*!
27  * @brief Clear auto registered lines in the picktype.prf .
28  */
29 static bool clear_auto_register(PlayerType *player_ptr)
30 {
31     auto path_pref = path_build(ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
32     auto *pref_fff = angband_fopen(path_pref, FileOpenMode::READ);
33     if (!pref_fff) {
34         path_pref = path_build(ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
35         pref_fff = angband_fopen(path_pref, FileOpenMode::READ);
36     }
37
38     if (!pref_fff) {
39         return true;
40     }
41
42     char tmp_file[1024];
43     auto *tmp_fff = angband_fopen_temp(tmp_file, sizeof(tmp_file));
44     if (!tmp_fff) {
45         fclose(pref_fff);
46         msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
47         msg_print(nullptr);
48         return false;
49     }
50
51     auto autoregister = false;
52     auto num = 0;
53     while (true) {
54         char buf[1024]{};
55         if (angband_fgets(pref_fff, buf, sizeof(buf))) {
56             break;
57         }
58
59         if (autoregister) {
60             if (buf[0] != '#' && buf[0] != '?') {
61                 num++;
62             }
63             continue;
64         }
65
66         if (streq(buf, autoregister_header)) {
67             autoregister = true;
68         } else {
69             fprintf(tmp_fff, "%s\n", buf);
70         }
71     }
72
73     angband_fclose(pref_fff);
74     angband_fclose(tmp_fff);
75
76     bool okay = true;
77     if (num) {
78         msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。", "Auto registered lines (%d lines) for previous character are remaining."), num);
79         constexpr auto mes = _("古い設定行は削除します。よろしいですか?", "These lines will be deleted.  Are you sure? ");
80
81         if (!get_check(mes)) {
82             okay = false;
83             autoregister = false;
84
85             msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。", "Use cut & paste of auto picker editor (_) to keep old prefs."));
86         }
87     }
88
89     if (autoregister) {
90         tmp_fff = angband_fopen(tmp_file, FileOpenMode::READ);
91         pref_fff = angband_fopen(path_pref, FileOpenMode::WRITE);
92         char buf[1024]{};
93         while (!angband_fgets(tmp_fff, buf, sizeof(buf))) {
94             fprintf(pref_fff, "%s\n", buf);
95         }
96
97         angband_fclose(pref_fff);
98         angband_fclose(tmp_fff);
99     }
100
101     fd_kill(tmp_file);
102     return okay;
103 }
104
105 /*!
106  * @brief Automatically register an auto-destroy preference line
107  */
108 bool autopick_autoregister(PlayerType *player_ptr, ItemEntity *o_ptr)
109 {
110     autopick_type an_entry, *entry = &an_entry;
111     int autopick_registered = find_autopick_list(player_ptr, o_ptr);
112     if (autopick_registered != -1) {
113         concptr what;
114         byte act = autopick_list[autopick_registered].action;
115         if (act & DO_AUTOPICK) {
116             what = _("自動で拾う", "auto-pickup");
117         } else if (act & DO_AUTODESTROY) {
118             what = _("自動破壊する", "auto-destroy");
119         } else if (act & DONT_AUTOPICK) {
120             what = _("放置する", "leave on floor");
121         } else {
122             what = _("確認して拾う", "query auto-pickup");
123         }
124
125         msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
126         return false;
127     }
128
129     if ((o_ptr->is_known() && o_ptr->is_fixed_or_random_artifact()) || ((o_ptr->ident & IDENT_SENSE) && (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL))) {
130         const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
131         msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), item_name.data());
132         return false;
133     }
134
135     if (!player_ptr->autopick_autoregister) {
136         if (!clear_auto_register(player_ptr)) {
137             return false;
138         }
139     }
140
141     const auto path_pref = path_build(ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
142     auto *pref_fff = angband_fopen(path_pref, FileOpenMode::READ);
143     if (!pref_fff) {
144         path_build(ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
145         pref_fff = angband_fopen(path_pref, FileOpenMode::READ);
146     }
147
148     if (pref_fff) {
149         while (true) {
150             char buf[1024]{};
151             if (angband_fgets(pref_fff, buf, sizeof(buf))) {
152                 player_ptr->autopick_autoregister = false;
153                 break;
154             }
155
156             if (streq(buf, autoregister_header)) {
157                 player_ptr->autopick_autoregister = true;
158                 break;
159             }
160         }
161
162         fclose(pref_fff);
163     } else {
164         /*
165          * File could not be opened for reading.  Assume header not
166          * present.
167          */
168         player_ptr->autopick_autoregister = false;
169     }
170
171     pref_fff = angband_fopen(path_pref, FileOpenMode::APPEND);
172     if (!pref_fff) {
173         const auto filename_pref = path_pref.string();
174         msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), filename_pref.data());
175         msg_print(nullptr);
176         return false;
177     }
178
179     if (!player_ptr->autopick_autoregister) {
180         fprintf(pref_fff, "%s\n", autoregister_header);
181
182         fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。", "# *Warning!* The lines below will be deleted later."));
183         fprintf(pref_fff, "%s\n",
184             _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。",
185                 "# Keep it by cut & paste if you need these lines for future characters."));
186         player_ptr->autopick_autoregister = true;
187     }
188
189     autopick_entry_from_object(player_ptr, entry, o_ptr);
190     entry->action = DO_AUTODESTROY;
191     autopick_list.push_back(*entry);
192
193     concptr tmp = autopick_line_from_entry(*entry);
194     fprintf(pref_fff, "%s\n", tmp);
195     string_free(tmp);
196     fclose(pref_fff);
197     return true;
198 }