OSDN Git Service

[Refactor] #37353 Separated hook-enchant.c/h from object-hook.c/h
[hengband/hengband.git] / src / knowledge / knowledge-inventory.c
1 /*
2  * @brief 装備の耐性を表示する
3  * @date 2020/04/20
4  * @author Hourier
5  */
6
7 #include "knowledge/knowledge-inventory.h"
8 #include "core/show-file.h"
9 #include "floor/floor-town.h"
10 #include "io-dump/dump-util.h"
11 #include "object-enchant/special-object-flags.h"
12 #include "object-enchant/tr-types.h"
13 #include "object-hook/hook-enchant.h"
14 #include "object-hook/hook-weapon.h"
15 #include "object/object-flags.h"
16 #include "object/object-flavor.h"
17 #include "perception/object-perception.h"
18 #include "store/store-util.h"
19 #include "sv-definition/sv-amulet-types.h"
20 #include "sv-definition/sv-protector-types.h"
21 #include "sv-definition/sv-ring-types.h"
22 #include "util/angband-files.h"
23 #include "util/bit-flags-calculator.h"
24
25 static concptr inven_res_label = _(
26         "                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
27         "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
28
29 #define IM_FLAG_STR  _("*", "* ")
30 #define HAS_FLAG_STR _("+", "+ ")
31 #define NO_FLAG_STR  _("・", ". ")
32
33
34 /*!
35  * @brief 4元素耐性を表示する
36  * @param immunity 4元素耐性の種類 (二重?)
37  * @param resistance 4元素耐性
38  * @param flags 耐性配列へのポインタ
39  * @param fff 一時ファイルへのポインタ
40  * @return なし
41  */
42 static void print_im_or_res_flag(int immunity, int resistance, BIT_FLAGS *flags, FILE *fff)
43 {
44         fputs(have_flag(flags, immunity) ? IM_FLAG_STR :
45               (have_flag(flags, resistance) ? HAS_FLAG_STR : NO_FLAG_STR), fff);
46 }
47
48
49 /*!
50  * @brief 4元素以外の耐性を表示する
51  * @param tr 耐性
52  * @param flags 耐性配列へのポインタ
53  * @param fff 一時ファイルへのポインタ
54  * @return なし
55  */
56 static void print_flag(int tr, BIT_FLAGS *flags, FILE *fff)
57 {
58         fputs(have_flag(flags, tr) ? HAS_FLAG_STR : NO_FLAG_STR, fff);
59 }
60
61
62 /*!
63  * @brief 特殊なアイテムかどうかを調べる
64  * @param o_ptr アイテムへの参照ポインタ
65  * @param tval アイテム主分類番号
66  * @return 特殊なアイテムならTRUE
67  */
68 static bool determine_spcial_item_type(object_type *o_ptr, tval_type tval)
69 {
70         bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
71                 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
72                 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
73                 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
74                 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
75                 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
76                 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
77                 || object_is_artifact(o_ptr);
78
79         return is_special_item_type;
80 }
81
82
83 /*!
84  * @brief アイテムに耐性の表示をする必要があるかを判定する
85  * @param o_ptr アイテムへの参照ポインタ
86  * @param tval アイテム主分類番号
87  * @return 必要があるならTRUE
88  */
89 static bool check_item_knowledge(object_type *o_ptr, tval_type tval)
90 {
91         if (o_ptr->k_idx == 0) return FALSE;
92         if (o_ptr->tval != tval) return FALSE;
93         if (!object_is_known(o_ptr)) return FALSE;
94         if (!determine_spcial_item_type(o_ptr, tval)) return FALSE;
95
96         return TRUE;
97 }
98
99
100 /*!
101  * todo ここの関数から表示用の関数に移したい
102  * @brief 鑑定済アイテムの耐性を表示する
103  * @param o_ptr アイテムへの参照ポインタ
104  * @param fff 一時ファイルへの参照ポインタ
105  * @return なし
106  */
107 static void display_identified_resistances_flag(player_type *creature_ptr, object_type *o_ptr, FILE *fff)
108 {
109         BIT_FLAGS flags[TR_FLAG_SIZE];
110     object_flags_known(creature_ptr, o_ptr, flags);
111
112         print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID, flags, fff);
113         print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC, flags, fff);
114         print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE, flags, fff);
115         print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD, flags, fff);
116         print_flag(TR_RES_POIS, flags, fff);
117         print_flag(TR_RES_LITE, flags, fff);
118         print_flag(TR_RES_DARK, flags, fff);
119         print_flag(TR_RES_SHARDS, flags, fff);
120         print_flag(TR_RES_SOUND, flags, fff);
121         print_flag(TR_RES_NETHER, flags, fff);
122         print_flag(TR_RES_NEXUS, flags, fff);
123         print_flag(TR_RES_CHAOS, flags, fff);
124         print_flag(TR_RES_DISEN, flags, fff);
125
126         fputs(" ", fff);
127
128         print_flag(TR_RES_BLIND, flags, fff);
129         print_flag(TR_RES_FEAR, flags, fff);
130         print_flag(TR_RES_CONF, flags, fff);
131         print_flag(TR_FREE_ACT, flags, fff);
132         print_flag(TR_SEE_INVIS, flags, fff);
133         print_flag(TR_HOLD_EXP, flags, fff);
134         print_flag(TR_TELEPATHY, flags, fff);
135         print_flag(TR_SLOW_DIGEST, flags, fff);
136         print_flag(TR_REGEN, flags, fff);
137         print_flag(TR_LEVITATION, flags, fff);
138
139         fputc('\n', fff);
140 }
141
142
143 /*!
144  * @brief アイテム1つ当たりの耐性を表示する
145  * @param creature_ptr プレーヤーへの参照ポインタ
146  * @param fff 一時ファイルへの参照ポインタ
147  * @param o_ptr アイテムへの参照ポインタ
148  * @param where アイテムの場所 (手持ち、家等) を示す文字列への参照ポインタ
149  * @return なし
150  */
151 static void do_cmd_knowledge_inventory_aux(player_type *creature_ptr, FILE *fff, object_type *o_ptr, char *where)
152 {
153         int i = 0;
154         GAME_TEXT o_name[MAX_NLEN];
155         object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
156         while (o_name[i] && (i < 26))
157         {
158 #ifdef JP
159                 if (iskanji(o_name[i])) i++;
160 #endif
161                 i++;
162         }
163
164         if (i < 28)
165         {
166                 while (i < 28)
167                 {
168                         o_name[i] = ' '; i++;
169                 }
170         }
171
172         o_name[i] = '\0';
173
174         fprintf(fff, "%s %s", where, o_name);
175
176         if (!object_is_fully_known(o_ptr))
177         {
178                 fputs(_("-------不明--------------- -------不明---------\n",
179                         "-------unknown------------ -------unknown------\n"), fff);
180                 return;
181         }
182
183         display_identified_resistances_flag(creature_ptr, o_ptr, fff);
184 }
185
186
187 /*!
188  * @brief 9行おきにラベルを追加する
189  * @param label_number 現在の行数
190  * @param fff 一時ファイルへの参照ポインタ
191  * @return なし
192  */
193 static void add_res_label(int *label_number, FILE *fff)
194 {
195         (*label_number)++;
196         if (*label_number == 9)
197         {
198                 *label_number = 0;
199                 fprintf(fff, "%s\n", inven_res_label);
200         }
201 }
202
203
204 /*!
205  * @brief 9行ごとに行数をリセットする
206  * @param label_number 現在の行数
207  * @param fff 一時ファイルへの参照ポインタ
208  * @return なし
209  */
210 static void reset_label_number(int *label_number, FILE *fff)
211 {
212         if (*label_number == 0) return;
213
214         for (; *label_number < 9; (*label_number)++)
215         {
216                 fputc('\n', fff);
217         }
218
219         *label_number = 0;
220         fprintf(fff, "%s\n", inven_res_label);
221 }
222
223
224 /*!
225  * 装備中のアイテムについて、耐性を表示する
226  * @param creature_ptr プレーヤーへの参照ポインタ
227  * @param tval アイテム主分類番号
228  * @param label_number 現在の行数
229  * @param fff ファイルへの参照ポインタ
230  * @return なし
231  */
232 static void show_wearing_equipment_resistances(player_type *creature_ptr, tval_type tval, int *label_number, FILE *fff)
233 {
234         char where[32];
235         strcpy(where, _("装", "E "));
236         for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
237         {
238                 object_type *o_ptr = &creature_ptr->inventory_list[i];
239                 if (!check_item_knowledge(o_ptr, tval))
240                         continue;
241
242                 do_cmd_knowledge_inventory_aux(creature_ptr, fff, o_ptr, where);
243                 add_res_label(label_number, fff);
244         }
245 }
246
247
248 /*!
249  * 手持ち中のアイテムについて、耐性を表示する
250  * @param creature_ptr プレーヤーへの参照ポインタ
251  * @param tval アイテム主分類番号
252  * @param label_number 現在の行数
253  * @param fff ファイルへの参照ポインタ
254  * @return なし
255  */
256 static void show_holding_equipment_resistances(player_type *creature_ptr, tval_type tval, int *label_number, FILE *fff)
257 {
258         char where[32];
259         strcpy(where, _("持", "I "));
260         for (int i = 0; i < INVEN_PACK; i++)
261         {
262                 object_type *o_ptr = &creature_ptr->inventory_list[i];
263                 if (!check_item_knowledge(o_ptr, tval))
264                         continue;
265
266                 do_cmd_knowledge_inventory_aux(creature_ptr, fff, o_ptr, where);
267                 add_res_label(label_number, fff);
268         }
269 }
270
271
272 /*!
273  * 我が家のアイテムについて、耐性を表示する
274  * @param creature_ptr プレーヤーへの参照ポインタ
275  * @param tval アイテム主分類番号
276  * @param label_number 現在の行数
277  * @param fff ファイルへの参照ポインタ
278  * @return なし
279  */
280 static void show_home_equipment_resistances(player_type *creature_ptr, tval_type tval, int *label_number, FILE *fff)
281 {
282         store_type *store_ptr;
283         store_ptr = &town_info[1].store[STORE_HOME];
284         char where[32];
285         strcpy(where, _("家", "H "));
286         for (int i = 0; i < store_ptr->stock_num; i++)
287         {
288                 object_type *o_ptr = &store_ptr->stock[i];
289                 if (!check_item_knowledge(o_ptr, tval))
290                         continue;
291
292                 do_cmd_knowledge_inventory_aux(creature_ptr, fff, o_ptr, where);
293                 add_res_label(label_number, fff);
294         }
295 }
296
297
298 /*
299  * @brief Display *ID* ed weapons/armors's resistances
300  * @param creature_ptr プレーヤーへの参照ポインタ
301  * @return なし
302  */
303 void do_cmd_knowledge_inventory(player_type *creature_ptr)
304 {
305         FILE *fff = NULL;
306         GAME_TEXT file_name[FILE_NAME_SIZE];
307         if (!open_temporary_file(&fff, file_name)) return;
308
309         fprintf(fff, "%s\n", inven_res_label);
310         int label_number = 0;
311         for (tval_type tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
312         {
313                 reset_label_number(&label_number, fff);
314                 show_wearing_equipment_resistances(creature_ptr, tval, &label_number, fff);
315                 show_holding_equipment_resistances(creature_ptr, tval, &label_number, fff);
316                 show_home_equipment_resistances(creature_ptr, tval, &label_number, fff);
317         }
318
319         angband_fclose(fff);
320         (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
321         fd_kill(file_name);
322 }