OSDN Git Service

[Refactor] #1511 「プレーヤー」表記を全て「プレイヤー」に変更した (日本語版のみ、ほぼDoxygenコメント)
[hengbandforosx/hengbandosx.git] / src / wizard / artifact-analyzer.cpp
1 #include "wizard/artifact-analyzer.h"
2 #include "flavor/flavor-describer.h"
3 #include "flavor/object-flavor-types.h"
4 #include "object-enchant/object-ego.h"
5 #include "object-enchant/trc-types.h"
6 #include "object-enchant/trg-types.h"
7 #include "object/object-flags.h"
8 #include "object/object-info.h"
9 #include "system/artifact-type-definition.h"
10 #include "system/object-type-definition.h"
11 #include "util/bit-flags-calculator.h"
12 #include "util/quarks.h"
13 #include "wizard/spoiler-util.h"
14
15 /*!
16  * @brief アーティファクトの特性一覧を出力する /
17  * Write a line to the spoiler file and then "underline" it with hypens
18  * @param art_flags アーティファクトのフラグ群
19  * @param flag_ptr フラグ記述情報の参照ポインタ
20  * @param desc_ptr 記述内容を返すための文字列参照ポインタ
21  * @param n_elmnts フラグの要素数
22  * @return desc_ptrと同じアドレス
23  * @details
24  * <pre>
25  * This function does most of the actual "analysis". Given a set of bit flags
26  * (which will be from one of the flags fields from the object in question),
27  * a "flag description structure", a "description list", and the number of
28  * elements in the "flag description structure", this function sets the
29  * "description list" members to the appropriate descriptions contained in
30  * the "flag description structure".
31  * The possibly updated description pointer is returned.
32  * </pre>
33  */
34 static concptr *spoiler_flag_aux(const TrFlags &art_flags, const flag_desc *flag_ptr, concptr *desc_ptr, const int n_elmnts)
35 {
36     for (int i = 0; i < n_elmnts; ++i)
37         if (art_flags.has(flag_ptr[i].flag))
38             *desc_ptr++ = flag_ptr[i].desc;
39
40     return desc_ptr;
41 }
42
43 /*!
44  * @brief アイテムの特定記述内容を返す /
45  * Acquire a "basic" description "The Cloak of Death [1,+10]"
46  * @param o_ptr 記述を得たいオブジェクトの参照ポインタ
47  * @param desc_ptr 記述内容を返すための文字列参照ポインタ
48  */
49 static void analyze_general(player_type *player_ptr, object_type *o_ptr, char *desc_ptr)
50 {
51     describe_flavor(player_ptr, desc_ptr, o_ptr, OD_NAME_AND_ENCHANT | OD_STORE | OD_DEBUG);
52 }
53
54 /*!
55  * @brief アーティファクトがプレイヤーに与えるpval修正を構造体に収める /
56  * List "player traits" altered by an artifact's pval. These include stats,
57  * speed, infravision, tunneling, stealth, searching, and extra attacks.
58  * @param o_ptr オブジェクト構造体の参照ポインタ
59  * @param pi_ptr pval修正構造体の参照ポインタ
60  */
61 static void analyze_pval(object_type *o_ptr, pval_info_type *pi_ptr)
62 {
63     concptr *affects_list;
64     if (!o_ptr->pval) {
65         pi_ptr->pval_desc[0] = '\0';
66         return;
67     }
68
69     auto flgs = object_flags(o_ptr);
70     affects_list = pi_ptr->pval_affects;
71     sprintf(pi_ptr->pval_desc, "%s%d", o_ptr->pval >= 0 ? "+" : "", o_ptr->pval);
72     if (flgs.has(TR_STR) && flgs.has(TR_INT) && flgs.has(TR_WIS) && flgs.has(TR_DEX) && flgs.has(TR_CON)
73         && flgs.has(TR_CHR)) {
74         *affects_list++ = _("全能力", "All stats");
75     } else if (flgs.has(TR_STR) || flgs.has(TR_INT) || flgs.has(TR_WIS) || flgs.has(TR_DEX) || flgs.has(TR_CON)
76         || flgs.has(TR_CHR)) {
77         affects_list = spoiler_flag_aux(flgs, stat_flags_desc, affects_list, N_ELEMENTS(stat_flags_desc));
78     }
79
80     affects_list = spoiler_flag_aux(flgs, pval_flags1_desc, affects_list, N_ELEMENTS(pval_flags1_desc));
81     *affects_list = nullptr;
82 }
83
84 /*!
85  * @brief アーティファクトの種族スレイ特性を構造体に収める /
86  * Note the slaying specialties of a weapon
87  * @param o_ptr オブジェクト構造体の参照ポインタ
88  * @param slay_list 種族スレイ構造体の参照ポインタ
89  */
90 static void analyze_slay(object_type *o_ptr, concptr *slay_list)
91 {
92     auto flgs = object_flags(o_ptr);
93     slay_list = spoiler_flag_aux(flgs, slay_flags_desc, slay_list, N_ELEMENTS(slay_flags_desc));
94     *slay_list = nullptr;
95 }
96
97 /*!
98  * @brief アーティファクトの属性ブランド特性を構造体に収める /
99  * Note an object's elemental brands
100  * @param o_ptr オブジェクト構造体の参照ポインタ
101  * @param brand_list 属性ブランド構造体の参照ポインタ
102  */
103 static void analyze_brand(object_type *o_ptr, concptr *brand_list)
104 {
105     auto flgs = object_flags(o_ptr);
106     brand_list = spoiler_flag_aux(flgs, brand_flags_desc, brand_list, N_ELEMENTS(brand_flags_desc));
107     *brand_list = nullptr;
108 }
109
110 /*!
111  * @brief アーティファクトの通常耐性を構造体に収める /
112  * Note an object's elemental brands
113  * @param o_ptr オブジェクト構造体の参照ポインタ
114  * @param resist_list 通常耐性構造体の参照ポインタ
115  */
116 static void analyze_resist(object_type *o_ptr, concptr *resist_list)
117 {
118     auto flgs = object_flags(o_ptr);
119     resist_list = spoiler_flag_aux(flgs, resist_flags_desc, resist_list, N_ELEMENTS(resist_flags_desc));
120     *resist_list = nullptr;
121 }
122
123 /*!
124  * @brief アーティファクトの免疫特性を構造体に収める /
125  * Note the immunities granted by an object
126  * @param o_ptr オブジェクト構造体の参照ポインタ
127  * @param immune_list 免疫構造体の参照ポインタ
128  */
129 static void analyze_immune(object_type *o_ptr, concptr *immune_list)
130 {
131     auto flgs = object_flags(o_ptr);
132     immune_list = spoiler_flag_aux(flgs, immune_flags_desc, immune_list, N_ELEMENTS(immune_flags_desc));
133     *immune_list = nullptr;
134 }
135
136 /*!
137  * @brief アーティファクトの維持特性を構造体に収める /
138  * Note which stats an object sustains
139  * @param o_ptr オブジェクト構造体の参照ポインタ
140  * @param sustain_list 維持特性構造体の参照ポインタ
141  */
142 static void analyze_sustains(object_type *o_ptr, concptr *sustain_list)
143 {
144     auto flgs = object_flags(o_ptr);
145     if (flgs.has(TR_SUST_STR) && flgs.has(TR_SUST_INT) && flgs.has(TR_SUST_WIS) && flgs.has(TR_SUST_DEX)
146         && flgs.has(TR_SUST_CON) && flgs.has(TR_SUST_CHR)) {
147         *sustain_list++ = _("全能力", "All stats");
148     } else if (flgs.has(TR_SUST_STR) || flgs.has(TR_SUST_INT) || flgs.has(TR_SUST_WIS) || flgs.has(TR_SUST_DEX)
149         || flgs.has(TR_SUST_CON) || flgs.has(TR_SUST_CHR)) {
150         sustain_list = spoiler_flag_aux(flgs, sustain_flags_desc, sustain_list, N_ELEMENTS(sustain_flags_desc));
151     }
152
153     *sustain_list = nullptr;
154 }
155
156 /*!
157  * @brief アーティファクトのその他の特性を構造体に収める /
158  * Note miscellaneous powers bestowed by an artifact such as see invisible,
159  * free action, permanent light, etc.
160  * @param o_ptr オブジェクト構造体の参照ポインタ
161  * @param misc_list その他の特性構造体の参照ポインタ
162  */
163 static void analyze_misc_magic(object_type *o_ptr, concptr *misc_list)
164 {
165     char desc[256];
166
167     auto flgs = object_flags(o_ptr);
168     misc_list = spoiler_flag_aux(flgs, misc_flags2_desc, misc_list, N_ELEMENTS(misc_flags2_desc));
169     misc_list = spoiler_flag_aux(flgs, misc_flags3_desc, misc_list, N_ELEMENTS(misc_flags3_desc));
170     POSITION rad = 0;
171     if (flgs.has(TR_LITE_1))
172         rad += 1;
173
174     if (flgs.has(TR_LITE_2))
175         rad += 2;
176
177     if (flgs.has(TR_LITE_3))
178         rad += 3;
179
180     if (flgs.has(TR_LITE_M1))
181         rad -= 1;
182
183     if (flgs.has(TR_LITE_M2))
184         rad -= 2;
185
186     if (flgs.has(TR_LITE_M3))
187         rad -= 3;
188
189     if (o_ptr->name2 == EGO_LITE_SHINE)
190         rad++;
191
192     if (flgs.has(TR_LITE_FUEL)) {
193         if (rad > 0)
194             sprintf(desc, _("それは燃料補給によって明かり(半径 %d)を授ける。", "It provides light (radius %d) when fueled."), (int)rad);
195     } else {
196         if (rad > 0)
197             sprintf(desc, _("永久光源(半径 %d)", "Permanent Light(radius %d)"), (int)rad);
198
199         if (rad < 0)
200             sprintf(desc, _("永久光源(半径-%d)。", "Permanent Light(radius -%d)"), (int)-rad);
201     }
202
203     if (rad != 0)
204         *misc_list++ = quark_str(quark_add(desc));
205
206     if (flgs.has(TR_TY_CURSE))
207         *misc_list++ = _("太古の怨念", "Ancient Curse");
208
209     if (o_ptr->curse_flags.has(TRC::PERMA_CURSE))
210         *misc_list++ = _("永遠の呪い", "Permanently Cursed");
211     else if (o_ptr->curse_flags.has(TRC::HEAVY_CURSE))
212         *misc_list++ = _("強力な呪い", "Heavily Cursed");
213     else if (o_ptr->curse_flags.has(TRC::CURSED))
214         *misc_list++ = _("呪い", "Cursed");
215
216     if (flgs.has(TR_ADD_L_CURSE))
217         *misc_list++ = _("呪いを増やす", "Cursing");
218
219     if (flgs.has(TR_ADD_H_CURSE))
220         *misc_list++ = _("強力な呪いを増やす", "Heavily Cursing");
221
222     *misc_list = nullptr;
223 }
224
225 /*!
226  * @brief アーティファクトの追加ランダム特性を構造体に収める /
227  * Note additional ability and/or resistance of fixed artifacts
228  * @param o_ptr オブジェクト構造体の参照ポインタ
229  * @param addition 追加ランダム耐性構造体の参照ポインタ
230  */
231 static void analyze_addition(object_type *o_ptr, char *addition)
232 {
233     artifact_type *a_ptr = &a_info[o_ptr->name1];
234     strcpy(addition, "");
235
236     if (a_ptr->gen_flags.has_all_of({ TRG::XTRA_POWER, TRG::XTRA_H_RES })) {
237         strcat(addition, _("能力and耐性", "Ability and Resistance"));
238     } else if (a_ptr->gen_flags.has(TRG::XTRA_POWER)) {
239         strcat(addition, _("能力", "Ability"));
240         if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
241             strcat(addition, _("(1/2でand耐性)", "(plus Resistance about 1/2)"));
242     } else if (a_ptr->gen_flags.has(TRG::XTRA_H_RES)) {
243         strcat(addition, _("耐性", "Resistance"));
244         if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
245             strcat(addition, _("(1/2でand能力)", "(plus Ability about 1/2)"));
246     } else if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
247         strcat(addition, _("能力or耐性", "Ability or Resistance"));
248
249     if (a_ptr->gen_flags.has(TRG::XTRA_DICE)) {
250         if (strlen(addition) > 0)
251             strcat(addition, _("、", ", "));
252         strcat(addition, _("ダイス数", "Dice number"));
253     }
254 }
255
256 /*!
257  * @brief アーティファクトの基本情報を文字列に収める /
258  * Determine the minimum depth an artifact can appear, its rarity, its weight,
259  * and its value in gold pieces
260  * @param o_ptr オブジェクト構造体の参照ポインタ
261  * @param misc_desc 基本情報を収める文字列参照ポインタ
262  */
263 static void analyze_misc(object_type *o_ptr, char *misc_desc)
264 {
265     artifact_type *a_ptr = &a_info[o_ptr->name1];
266     sprintf(misc_desc, _("レベル %d, 希少度 %u, %d.%d kg, $%ld", "Level %d, Rarity %u, %d.%d lbs, %ld Gold"), (int)a_ptr->level, a_ptr->rarity,
267         _(lbtokg1(a_ptr->weight), a_ptr->weight / 10), _(lbtokg2(a_ptr->weight), a_ptr->weight % 10), (long int)a_ptr->cost);
268 }
269
270 /*!
271  * @brief アーティファクトの情報全体を構造体に収める /
272  * Fill in an object description structure for a given object
273  * and its value in gold pieces
274  * @param player_ptr プレイヤーへの参照ポインタ
275  * @param o_ptr オブジェクト構造体の参照ポインタ
276  * @param desc_ptr 全アーティファクト情報を収める文字列参照ポインタ
277  */
278 void object_analyze(player_type *player_ptr, object_type *o_ptr, obj_desc_list *desc_ptr)
279 {
280     analyze_general(player_ptr, o_ptr, desc_ptr->description);
281     analyze_pval(o_ptr, &desc_ptr->pval_info);
282     analyze_brand(o_ptr, desc_ptr->brands);
283     analyze_slay(o_ptr, desc_ptr->slays);
284     analyze_immune(o_ptr, desc_ptr->immunities);
285     analyze_resist(o_ptr, desc_ptr->resistances);
286     analyze_sustains(o_ptr, desc_ptr->sustains);
287     analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
288     analyze_addition(o_ptr, desc_ptr->addition);
289     analyze_misc(o_ptr, desc_ptr->misc_desc);
290     desc_ptr->activation = activation_explanation(o_ptr);
291 }
292
293 /*!
294  * @brief ランダムアーティファクト1件を解析する /
295  * Fill in an object description structure for a given object
296  * @param player_ptr プレイヤーへの参照ポインタ
297  * @param o_ptr ランダムアーティファクトのオブジェクト構造体参照ポインタ
298  * @param desc_ptr 記述内容を収める構造体参照ポインタ
299  */
300 void random_artifact_analyze(player_type *player_ptr, object_type *o_ptr, obj_desc_list *desc_ptr)
301 {
302     analyze_general(player_ptr, o_ptr, desc_ptr->description);
303     analyze_pval(o_ptr, &desc_ptr->pval_info);
304     analyze_brand(o_ptr, desc_ptr->brands);
305     analyze_slay(o_ptr, desc_ptr->slays);
306     analyze_immune(o_ptr, desc_ptr->immunities);
307     analyze_resist(o_ptr, desc_ptr->resistances);
308     analyze_sustains(o_ptr, desc_ptr->sustains);
309     analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
310     desc_ptr->activation = activation_explanation(o_ptr);
311     sprintf(desc_ptr->misc_desc, _("重さ %d.%d kg", "Weight %d.%d lbs"), _(lbtokg1(o_ptr->weight), o_ptr->weight / 10),
312         _(lbtokg2(o_ptr->weight), o_ptr->weight % 10));
313 }