OSDN Git Service

Merge pull request #1755 from Thujopsis/feature/add-monster-Rabbit-of-Caerbannog
[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 "locale/japanese.h"
5 #include "object-enchant/object-ego.h"
6 #include "object-enchant/trc-types.h"
7 #include "object-enchant/trg-types.h"
8 #include "object/object-flags.h"
9 #include "object/object-info.h"
10 #include "system/artifact-type-definition.h"
11 #include "system/object-type-definition.h"
12 #include "util/bit-flags-calculator.h"
13 #include "util/enum-range.h"
14 #include "util/quarks.h"
15 #include "wizard/spoiler-util.h"
16
17 /*!
18  * @brief アーティファクトの特性一覧を出力する /
19  * Write a line to the spoiler file and then "underline" it with hypens
20  * @param art_flags アーティファクトのフラグ群
21  * @param flag_ptr フラグ記述情報の参照ポインタ
22  * @param desc_ptr 記述内容を返すための文字列参照ポインタ
23  * @param n_elmnts フラグの要素数
24  * @return desc_ptrと同じアドレス
25  * @details
26  * <pre>
27  * This function does most of the actual "analysis". Given a set of bit flags
28  * (which will be from one of the flags fields from the object in question),
29  * a "flag description structure", a "description list", and the number of
30  * elements in the "flag description structure", this function sets the
31  * "description list" members to the appropriate descriptions contained in
32  * the "flag description structure".
33  * The possibly updated description pointer is returned.
34  * </pre>
35  */
36 static concptr *spoiler_flag_aux(const TrFlags &art_flags, const flag_desc *flag_ptr, concptr *desc_ptr, const int n_elmnts)
37 {
38     for (int i = 0; i < n_elmnts; ++i)
39         if (art_flags.has(flag_ptr[i].flag))
40             *desc_ptr++ = flag_ptr[i].desc;
41
42     return desc_ptr;
43 }
44
45 /*!
46  * @brief アイテムの特定記述内容を返す /
47  * Acquire a "basic" description "The Cloak of Death [1,+10]"
48  * @param o_ptr 記述を得たいオブジェクトの参照ポインタ
49  * @param desc_ptr 記述内容を返すための文字列参照ポインタ
50  */
51 static void analyze_general(player_type *player_ptr, object_type *o_ptr, char *desc_ptr)
52 {
53     describe_flavor(player_ptr, desc_ptr, o_ptr, OD_NAME_AND_ENCHANT | OD_STORE | OD_DEBUG);
54 }
55
56 /*!
57  * @brief アーティファクトがプレイヤーに与えるpval修正を構造体に収める /
58  * List "player traits" altered by an artifact's pval. These include stats,
59  * speed, infravision, tunneling, stealth, searching, and extra attacks.
60  * @param o_ptr オブジェクト構造体の参照ポインタ
61  * @param pi_ptr pval修正構造体の参照ポインタ
62  */
63 static void analyze_pval(object_type *o_ptr, pval_info_type *pi_ptr)
64 {
65     concptr *affects_list;
66     if (!o_ptr->pval) {
67         pi_ptr->pval_desc[0] = '\0';
68         return;
69     }
70
71     auto flgs = object_flags(o_ptr);
72     affects_list = pi_ptr->pval_affects;
73     sprintf(pi_ptr->pval_desc, "%s%d", o_ptr->pval >= 0 ? "+" : "", o_ptr->pval);
74     if (flgs.has_all_of(EnumRange(TR_STR, TR_CHR))) {
75         *affects_list++ = _("全能力", "All stats");
76     } else if (flgs.has_any_of(EnumRange(TR_STR, 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_all_of(EnumRange(TR_SUST_STR, TR_SUST_CHR))) {
146         *sustain_list++ = _("全能力", "All stats");
147     } else if (flgs.has_any_of(EnumRange(TR_SUST_STR, TR_SUST_CHR))) {
148         sustain_list = spoiler_flag_aux(flgs, sustain_flags_desc, sustain_list, N_ELEMENTS(sustain_flags_desc));
149     }
150
151     *sustain_list = nullptr;
152 }
153
154 /*!
155  * @brief アーティファクトのその他の特性を構造体に収める /
156  * Note miscellaneous powers bestowed by an artifact such as see invisible,
157  * free action, permanent light, etc.
158  * @param o_ptr オブジェクト構造体の参照ポインタ
159  * @param misc_list その他の特性構造体の参照ポインタ
160  */
161 static void analyze_misc_magic(object_type *o_ptr, concptr *misc_list)
162 {
163     char desc[256];
164
165     auto flgs = object_flags(o_ptr);
166     misc_list = spoiler_flag_aux(flgs, misc_flags2_desc, misc_list, N_ELEMENTS(misc_flags2_desc));
167     misc_list = spoiler_flag_aux(flgs, misc_flags3_desc, misc_list, N_ELEMENTS(misc_flags3_desc));
168     POSITION rad = 0;
169     if (flgs.has(TR_LITE_1))
170         rad += 1;
171
172     if (flgs.has(TR_LITE_2))
173         rad += 2;
174
175     if (flgs.has(TR_LITE_3))
176         rad += 3;
177
178     if (flgs.has(TR_LITE_M1))
179         rad -= 1;
180
181     if (flgs.has(TR_LITE_M2))
182         rad -= 2;
183
184     if (flgs.has(TR_LITE_M3))
185         rad -= 3;
186
187     if (o_ptr->name2 == EGO_LITE_SHINE)
188         rad++;
189
190     if (flgs.has(TR_LITE_FUEL)) {
191         if (rad > 0)
192             sprintf(desc, _("それは燃料補給によって明かり(半径 %d)を授ける。", "It provides light (radius %d) when fueled."), (int)rad);
193     } else {
194         if (rad > 0)
195             sprintf(desc, _("永久光源(半径 %d)", "Permanent Light(radius %d)"), (int)rad);
196
197         if (rad < 0)
198             sprintf(desc, _("永久光源(半径-%d)。", "Permanent Light(radius -%d)"), (int)-rad);
199     }
200
201     if (rad != 0)
202         *misc_list++ = quark_str(quark_add(desc));
203
204     if (flgs.has(TR_TY_CURSE))
205         *misc_list++ = _("太古の怨念", "Ancient Curse");
206
207     if (o_ptr->curse_flags.has(TRC::PERMA_CURSE))
208         *misc_list++ = _("永遠の呪い", "Permanently Cursed");
209     else if (o_ptr->curse_flags.has(TRC::HEAVY_CURSE))
210         *misc_list++ = _("強力な呪い", "Heavily Cursed");
211     else if (o_ptr->curse_flags.has(TRC::CURSED))
212         *misc_list++ = _("呪い", "Cursed");
213
214     if (flgs.has(TR_ADD_L_CURSE))
215         *misc_list++ = _("呪いを増やす", "Cursing");
216
217     if (flgs.has(TR_ADD_H_CURSE))
218         *misc_list++ = _("強力な呪いを増やす", "Heavily Cursing");
219
220     *misc_list = nullptr;
221 }
222
223 /*!
224  * @brief アーティファクトの追加ランダム特性を構造体に収める /
225  * Note additional ability and/or resistance of fixed artifacts
226  * @param o_ptr オブジェクト構造体の参照ポインタ
227  * @param addition 追加ランダム耐性構造体の参照ポインタ
228  */
229 static void analyze_addition(object_type *o_ptr, char *addition)
230 {
231     artifact_type *a_ptr = &a_info[o_ptr->name1];
232     strcpy(addition, "");
233
234     if (a_ptr->gen_flags.has_all_of({ TRG::XTRA_POWER, TRG::XTRA_H_RES })) {
235         strcat(addition, _("能力and耐性", "Ability and Resistance"));
236     } else if (a_ptr->gen_flags.has(TRG::XTRA_POWER)) {
237         strcat(addition, _("能力", "Ability"));
238         if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
239             strcat(addition, _("(1/2でand耐性)", "(plus Resistance about 1/2)"));
240     } else if (a_ptr->gen_flags.has(TRG::XTRA_H_RES)) {
241         strcat(addition, _("耐性", "Resistance"));
242         if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
243             strcat(addition, _("(1/2でand能力)", "(plus Ability about 1/2)"));
244     } else if (a_ptr->gen_flags.has(TRG::XTRA_RES_OR_POWER))
245         strcat(addition, _("能力or耐性", "Ability or Resistance"));
246
247     if (a_ptr->gen_flags.has(TRG::XTRA_DICE)) {
248         if (strlen(addition) > 0)
249             strcat(addition, _("、", ", "));
250         strcat(addition, _("ダイス数", "Dice number"));
251     }
252 }
253
254 /*!
255  * @brief アーティファクトの基本情報を文字列に収める /
256  * Determine the minimum depth an artifact can appear, its rarity, its weight,
257  * and its value in gold pieces
258  * @param o_ptr オブジェクト構造体の参照ポインタ
259  * @param misc_desc 基本情報を収める文字列参照ポインタ
260  */
261 static void analyze_misc(object_type *o_ptr, char *misc_desc)
262 {
263     artifact_type *a_ptr = &a_info[o_ptr->name1];
264     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,
265         _(lb_to_kg_integer(a_ptr->weight), a_ptr->weight / 10), _(lb_to_kg_fraction(a_ptr->weight), a_ptr->weight % 10), (long int)a_ptr->cost);
266 }
267
268 /*!
269  * @brief アーティファクトの情報全体を構造体に収める /
270  * Fill in an object description structure for a given object
271  * and its value in gold pieces
272  * @param player_ptr プレイヤーへの参照ポインタ
273  * @param o_ptr オブジェクト構造体の参照ポインタ
274  * @param desc_ptr 全アーティファクト情報を収める文字列参照ポインタ
275  */
276 void object_analyze(player_type *player_ptr, object_type *o_ptr, obj_desc_list *desc_ptr)
277 {
278     analyze_general(player_ptr, o_ptr, desc_ptr->description);
279     analyze_pval(o_ptr, &desc_ptr->pval_info);
280     analyze_brand(o_ptr, desc_ptr->brands);
281     analyze_slay(o_ptr, desc_ptr->slays);
282     analyze_immune(o_ptr, desc_ptr->immunities);
283     analyze_resist(o_ptr, desc_ptr->resistances);
284     analyze_sustains(o_ptr, desc_ptr->sustains);
285     analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
286     analyze_addition(o_ptr, desc_ptr->addition);
287     analyze_misc(o_ptr, desc_ptr->misc_desc);
288     desc_ptr->activation = activation_explanation(o_ptr);
289 }
290
291 /*!
292  * @brief ランダムアーティファクト1件を解析する /
293  * Fill in an object description structure for a given object
294  * @param player_ptr プレイヤーへの参照ポインタ
295  * @param o_ptr ランダムアーティファクトのオブジェクト構造体参照ポインタ
296  * @param desc_ptr 記述内容を収める構造体参照ポインタ
297  */
298 void random_artifact_analyze(player_type *player_ptr, object_type *o_ptr, obj_desc_list *desc_ptr)
299 {
300     analyze_general(player_ptr, o_ptr, desc_ptr->description);
301     analyze_pval(o_ptr, &desc_ptr->pval_info);
302     analyze_brand(o_ptr, desc_ptr->brands);
303     analyze_slay(o_ptr, desc_ptr->slays);
304     analyze_immune(o_ptr, desc_ptr->immunities);
305     analyze_resist(o_ptr, desc_ptr->resistances);
306     analyze_sustains(o_ptr, desc_ptr->sustains);
307     analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
308     desc_ptr->activation = activation_explanation(o_ptr);
309     sprintf(desc_ptr->misc_desc, _("重さ %d.%d kg", "Weight %d.%d lbs"), _(lb_to_kg_integer(o_ptr->weight), o_ptr->weight / 10),
310         _(lb_to_kg_fraction(o_ptr->weight), o_ptr->weight % 10));
311 }