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-converter.h"
14 #include "util/enum-range.h"
15 #include "util/quarks.h"
16 #include "wizard/spoiler-util.h"
19 * @brief アーティファクトの特性一覧を出力する /
20 * Write a line to the spoiler file and then "underline" it with hypens
21 * @param art_flags アーティファクトのフラグ群
22 * @param flag_ptr フラグ記述情報の参照ポインタ
23 * @param desc_ptr 記述内容を返すための文字列参照ポインタ
24 * @param n_elmnts フラグの要素数
25 * @return desc_ptrと同じアドレス
28 * This function does most of the actual "analysis". Given a set of bit flags
29 * (which will be from one of the flags fields from the object in question),
30 * a "flag description structure", a "description list", and the number of
31 * elements in the "flag description structure", this function sets the
32 * "description list" members to the appropriate descriptions contained in
33 * the "flag description structure".
34 * The possibly updated description pointer is returned.
37 static concptr *spoiler_flag_aux(const TrFlags &art_flags, const flag_desc *flag_ptr, concptr *desc_ptr, const int n_elmnts)
39 for (int i = 0; i < n_elmnts; ++i) {
40 if (art_flags.has(flag_ptr[i].flag)) {
41 *desc_ptr++ = flag_ptr[i].desc;
49 * @brief アイテムの特定記述内容を返す /
50 * Acquire a "basic" description "The Cloak of Death [1,+10]"
51 * @param o_ptr 記述を得たいオブジェクトの参照ポインタ
52 * @param desc_ptr 記述内容を返すための文字列参照ポインタ
54 static void analyze_general(PlayerType *player_ptr, ObjectType *o_ptr, char *desc_ptr)
56 describe_flavor(player_ptr, desc_ptr, o_ptr, OD_NAME_AND_ENCHANT | OD_STORE | OD_DEBUG);
60 * @brief アーティファクトがプレイヤーに与えるpval修正を構造体に収める /
61 * List "player traits" altered by an artifact's pval. These include stats,
62 * speed, infravision, tunneling, stealth, searching, and extra attacks.
63 * @param o_ptr オブジェクト構造体の参照ポインタ
64 * @param pi_ptr pval修正構造体の参照ポインタ
66 static void analyze_pval(ObjectType *o_ptr, pval_info_type *pi_ptr)
68 concptr *affects_list;
70 pi_ptr->pval_desc[0] = '\0';
74 auto flgs = object_flags(o_ptr);
75 affects_list = pi_ptr->pval_affects;
76 sprintf(pi_ptr->pval_desc, "%s%d", o_ptr->pval >= 0 ? "+" : "", o_ptr->pval);
77 if (flgs.has_all_of(EnumRange(TR_STR, TR_CHR))) {
78 *affects_list++ = _("全能力", "All stats");
79 } else if (flgs.has_any_of(EnumRange(TR_STR, TR_CHR))) {
80 affects_list = spoiler_flag_aux(flgs, stat_flags_desc, affects_list, N_ELEMENTS(stat_flags_desc));
83 affects_list = spoiler_flag_aux(flgs, pval_flags1_desc, affects_list, N_ELEMENTS(pval_flags1_desc));
84 *affects_list = nullptr;
88 * @brief アーティファクトの種族スレイ特性を構造体に収める /
89 * Note the slaying specialties of a weapon
90 * @param o_ptr オブジェクト構造体の参照ポインタ
91 * @param slay_list 種族スレイ構造体の参照ポインタ
93 static void analyze_slay(ObjectType *o_ptr, concptr *slay_list)
95 auto flgs = object_flags(o_ptr);
96 slay_list = spoiler_flag_aux(flgs, slay_flags_desc, slay_list, N_ELEMENTS(slay_flags_desc));
101 * @brief アーティファクトの属性ブランド特性を構造体に収める /
102 * Note an object's elemental brands
103 * @param o_ptr オブジェクト構造体の参照ポインタ
104 * @param brand_list 属性ブランド構造体の参照ポインタ
106 static void analyze_brand(ObjectType *o_ptr, concptr *brand_list)
108 auto flgs = object_flags(o_ptr);
109 brand_list = spoiler_flag_aux(flgs, brand_flags_desc, brand_list, N_ELEMENTS(brand_flags_desc));
110 *brand_list = nullptr;
114 * @brief アーティファクトの通常耐性を構造体に収める /
115 * Note an object's elemental brands
116 * @param o_ptr オブジェクト構造体の参照ポインタ
117 * @param resist_list 通常耐性構造体の参照ポインタ
119 static void analyze_resist(ObjectType *o_ptr, concptr *resist_list)
121 auto flgs = object_flags(o_ptr);
122 resist_list = spoiler_flag_aux(flgs, resist_flags_desc, resist_list, N_ELEMENTS(resist_flags_desc));
123 *resist_list = nullptr;
127 * @brief アーティファクトの免疫特性を構造体に収める /
128 * Note the immunities granted by an object
129 * @param o_ptr オブジェクト構造体の参照ポインタ
130 * @param immune_list 免疫構造体の参照ポインタ
132 static void analyze_immune(ObjectType *o_ptr, concptr *immune_list)
134 auto flgs = object_flags(o_ptr);
135 immune_list = spoiler_flag_aux(flgs, immune_flags_desc, immune_list, N_ELEMENTS(immune_flags_desc));
136 *immune_list = nullptr;
140 * @brief アーティファクトの弱点付与を構造体に収める /
141 * Note the immunities granted by an object
142 * @param o_ptr オブジェクト構造体の参照ポインタ
143 * @param immune_list 弱点構造体の参照ポインタ
145 static void analyze_vulnerable(ObjectType *o_ptr, concptr *vulnerable_list)
147 auto flgs = object_flags(o_ptr);
148 vulnerable_list = spoiler_flag_aux(flgs, vulnerable_flags_desc, vulnerable_list, N_ELEMENTS(vulnerable_flags_desc));
149 *vulnerable_list = nullptr;
153 * @brief アーティファクトの維持特性を構造体に収める /
154 * Note which stats an object sustains
155 * @param o_ptr オブジェクト構造体の参照ポインタ
156 * @param sustain_list 維持特性構造体の参照ポインタ
158 static void analyze_sustains(ObjectType *o_ptr, concptr *sustain_list)
160 auto flgs = object_flags(o_ptr);
161 if (flgs.has_all_of(EnumRange(TR_SUST_STR, TR_SUST_CHR))) {
162 *sustain_list++ = _("全能力", "All stats");
163 } else if (flgs.has_any_of(EnumRange(TR_SUST_STR, TR_SUST_CHR))) {
164 sustain_list = spoiler_flag_aux(flgs, sustain_flags_desc, sustain_list, N_ELEMENTS(sustain_flags_desc));
167 *sustain_list = nullptr;
171 * @brief アーティファクトのその他の特性を構造体に収める /
172 * Note miscellaneous powers bestowed by an artifact such as see invisible,
173 * free action, permanent light, etc.
174 * @param o_ptr オブジェクト構造体の参照ポインタ
175 * @param misc_list その他の特性構造体の参照ポインタ
177 static void analyze_misc_magic(ObjectType *o_ptr, concptr *misc_list)
181 auto flgs = object_flags(o_ptr);
182 misc_list = spoiler_flag_aux(flgs, misc_flags2_desc, misc_list, N_ELEMENTS(misc_flags2_desc));
183 misc_list = spoiler_flag_aux(flgs, misc_flags3_desc, misc_list, N_ELEMENTS(misc_flags3_desc));
185 if (flgs.has(TR_LITE_1)) {
189 if (flgs.has(TR_LITE_2)) {
193 if (flgs.has(TR_LITE_3)) {
197 if (flgs.has(TR_LITE_M1)) {
201 if (flgs.has(TR_LITE_M2)) {
205 if (flgs.has(TR_LITE_M3)) {
209 if (o_ptr->ego_idx == EgoType::LITE_SHINE) {
213 if (flgs.has(TR_LITE_FUEL)) {
215 sprintf(desc, _("それは燃料補給によって明かり(半径 %d)を授ける。", "It provides light (radius %d) when fueled."), (int)rad);
219 sprintf(desc, _("永久光源(半径 %d)", "Permanent Light(radius %d)"), (int)rad);
223 sprintf(desc, _("永久光源(半径-%d)。", "Permanent Light(radius -%d)"), (int)-rad);
228 *misc_list++ = quark_str(quark_add(desc));
231 if (flgs.has(TR_TY_CURSE)) {
232 *misc_list++ = _("太古の怨念", "Ancient Curse");
235 if (o_ptr->curse_flags.has(CurseTraitType::PERMA_CURSE)) {
236 *misc_list++ = _("永遠の呪い", "Permanently Cursed");
237 } else if (o_ptr->curse_flags.has(CurseTraitType::HEAVY_CURSE)) {
238 *misc_list++ = _("強力な呪い", "Heavily Cursed");
239 } else if (o_ptr->curse_flags.has(CurseTraitType::CURSED)) {
240 *misc_list++ = _("呪い", "Cursed");
243 if (flgs.has(TR_ADD_L_CURSE)) {
244 *misc_list++ = _("呪いを増やす", "Cursing");
247 if (flgs.has(TR_ADD_H_CURSE)) {
248 *misc_list++ = _("強力な呪いを増やす", "Heavily Cursing");
251 *misc_list = nullptr;
255 * @brief アーティファクトの追加ランダム特性を構造体に収める /
256 * Note additional ability and/or resistance of fixed artifacts
257 * @param o_ptr オブジェクト構造体の参照ポインタ
258 * @param addition 追加ランダム耐性構造体の参照ポインタ
260 static void analyze_addition(ObjectType *o_ptr, char *addition)
262 auto *a_ptr = &a_info[enum2i(o_ptr->fixed_artifact_idx)];
263 strcpy(addition, "");
265 if (a_ptr->gen_flags.has_all_of({ ItemGenerationTraitType::XTRA_POWER, ItemGenerationTraitType::XTRA_H_RES })) {
266 strcat(addition, _("能力and耐性", "Ability and Resistance"));
267 } else if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_POWER)) {
268 strcat(addition, _("能力", "Ability"));
269 if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_RES_OR_POWER)) {
270 strcat(addition, _("(1/2でand耐性)", "(plus Resistance about 1/2)"));
272 } else if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_H_RES)) {
273 strcat(addition, _("耐性", "Resistance"));
274 if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_RES_OR_POWER)) {
275 strcat(addition, _("(1/2でand能力)", "(plus Ability about 1/2)"));
277 } else if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_RES_OR_POWER)) {
278 strcat(addition, _("能力or耐性", "Ability or Resistance"));
281 if (a_ptr->gen_flags.has(ItemGenerationTraitType::XTRA_DICE)) {
282 if (strlen(addition) > 0) {
283 strcat(addition, _("、", ", "));
285 strcat(addition, _("ダイス数", "Dice number"));
290 * @brief アーティファクトの基本情報を文字列に収める /
291 * Determine the minimum depth an artifact can appear, its rarity, its weight,
292 * and its value in gold pieces
293 * @param o_ptr オブジェクト構造体の参照ポインタ
294 * @param misc_desc 基本情報を収める文字列参照ポインタ
296 static void analyze_misc(ObjectType *o_ptr, char *misc_desc)
298 auto *a_ptr = &a_info[enum2i(o_ptr->fixed_artifact_idx)];
299 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,
300 _(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);
304 * @brief アーティファクトの情報全体を構造体に収める /
305 * Fill in an object description structure for a given object
306 * and its value in gold pieces
307 * @param player_ptr プレイヤーへの参照ポインタ
308 * @param o_ptr オブジェクト構造体の参照ポインタ
309 * @param desc_ptr 全アーティファクト情報を収める文字列参照ポインタ
311 void object_analyze(PlayerType *player_ptr, ObjectType *o_ptr, obj_desc_list *desc_ptr)
313 analyze_general(player_ptr, o_ptr, desc_ptr->description);
314 analyze_pval(o_ptr, &desc_ptr->pval_info);
315 analyze_brand(o_ptr, desc_ptr->brands);
316 analyze_slay(o_ptr, desc_ptr->slays);
317 analyze_immune(o_ptr, desc_ptr->immunities);
318 analyze_resist(o_ptr, desc_ptr->resistances);
319 analyze_vulnerable(o_ptr, desc_ptr->vulnerables);
320 analyze_sustains(o_ptr, desc_ptr->sustains);
321 analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
322 analyze_addition(o_ptr, desc_ptr->addition);
323 analyze_misc(o_ptr, desc_ptr->misc_desc);
324 desc_ptr->activation = activation_explanation(o_ptr);
328 * @brief ランダムアーティファクト1件を解析する /
329 * Fill in an object description structure for a given object
330 * @param player_ptr プレイヤーへの参照ポインタ
331 * @param o_ptr ランダムアーティファクトのオブジェクト構造体参照ポインタ
332 * @param desc_ptr 記述内容を収める構造体参照ポインタ
334 void random_artifact_analyze(PlayerType *player_ptr, ObjectType *o_ptr, obj_desc_list *desc_ptr)
336 analyze_general(player_ptr, o_ptr, desc_ptr->description);
337 analyze_pval(o_ptr, &desc_ptr->pval_info);
338 analyze_brand(o_ptr, desc_ptr->brands);
339 analyze_slay(o_ptr, desc_ptr->slays);
340 analyze_immune(o_ptr, desc_ptr->immunities);
341 analyze_resist(o_ptr, desc_ptr->resistances);
342 analyze_vulnerable(o_ptr, desc_ptr->vulnerables);
343 analyze_sustains(o_ptr, desc_ptr->sustains);
344 analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
345 desc_ptr->activation = activation_explanation(o_ptr);
346 sprintf(desc_ptr->misc_desc, _("重さ %d.%d kg", "Weight %d.%d lbs"), _(lb_to_kg_integer(o_ptr->weight), o_ptr->weight / 10),
347 _(lb_to_kg_fraction(o_ptr->weight), o_ptr->weight % 10));