OSDN Git Service

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