OSDN Git Service

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