OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / wizard / artifact-analyzer.c
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 BIT_FLAGS art_flags[TR_FLAG_SIZE], const flag_desc *flag_ptr, concptr *desc_ptr, const int n_elmnts)
35 {
36     for (int i = 0; i < n_elmnts; ++i)
37         if (have_flag(art_flags, 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  * @return なし
49  */
50 static void analyze_general(player_type *player_ptr, object_type *o_ptr, char *desc_ptr)
51 {
52     describe_flavor(player_ptr, desc_ptr, o_ptr, OD_NAME_AND_ENCHANT | OD_STORE);
53 }
54
55 /*!
56  * @brief アーティファクトがプレイヤーに与えるpval修正を構造体に収める /
57  * List "player traits" altered by an artifact's pval. These include stats,
58  * speed, infravision, tunneling, stealth, searching, and extra attacks.
59  * @param o_ptr オブジェクト構造体の参照ポインタ
60  * @param pi_ptr pval修正構造体の参照ポインタ
61  * @return なし
62  */
63 static void analyze_pval(player_type *player_ptr, object_type *o_ptr, pval_info_type *pi_ptr)
64 {
65     BIT_FLAGS flgs[TR_FLAG_SIZE];
66     concptr *affects_list;
67     if (!o_ptr->pval) {
68         pi_ptr->pval_desc[0] = '\0';
69         return;
70     }
71
72     object_flags(player_ptr, o_ptr, flgs);
73     affects_list = pi_ptr->pval_affects;
74     sprintf(pi_ptr->pval_desc, "%s%d", o_ptr->pval >= 0 ? "+" : "", o_ptr->pval);
75     if (have_flag(flgs, TR_STR) && have_flag(flgs, TR_INT) && have_flag(flgs, TR_WIS) && have_flag(flgs, TR_DEX) && have_flag(flgs, TR_CON)
76         && have_flag(flgs, TR_CHR)) {
77         *affects_list++ = _("全能力", "All stats");
78     } else if (have_flag(flgs, TR_STR) || have_flag(flgs, TR_INT) || have_flag(flgs, TR_WIS) || have_flag(flgs, TR_DEX) || have_flag(flgs, TR_CON)
79         || have_flag(flgs, TR_CHR)) {
80         affects_list = spoiler_flag_aux(flgs, stat_flags_desc, affects_list, N_ELEMENTS(stat_flags_desc));
81     }
82
83     affects_list = spoiler_flag_aux(flgs, pval_flags1_desc, affects_list, N_ELEMENTS(pval_flags1_desc));
84     *affects_list = NULL;
85 }
86
87 /*!
88  * @brief アーティファクトの種族スレイ特性を構造体に収める /
89  * Note the slaying specialties of a weapon
90  * @param o_ptr オブジェクト構造体の参照ポインタ
91  * @param slay_list 種族スレイ構造体の参照ポインタ
92  * @return なし
93  */
94 static void analyze_slay(player_type *player_ptr, object_type *o_ptr, concptr *slay_list)
95 {
96     BIT_FLAGS flgs[TR_FLAG_SIZE];
97     object_flags(player_ptr, o_ptr, flgs);
98     slay_list = spoiler_flag_aux(flgs, slay_flags_desc, slay_list, N_ELEMENTS(slay_flags_desc));
99     *slay_list = NULL;
100 }
101
102 /*!
103  * @brief アーティファクトの属性ブランド特性を構造体に収める /
104  * Note an object's elemental brands
105  * @param o_ptr オブジェクト構造体の参照ポインタ
106  * @param brand_list 属性ブランド構造体の参照ポインタ
107  * @return なし
108  */
109 static void analyze_brand(player_type *player_ptr, object_type *o_ptr, concptr *brand_list)
110 {
111     BIT_FLAGS flgs[TR_FLAG_SIZE];
112     object_flags(player_ptr, o_ptr, flgs);
113     brand_list = spoiler_flag_aux(flgs, brand_flags_desc, brand_list, N_ELEMENTS(brand_flags_desc));
114     *brand_list = NULL;
115 }
116
117 /*!
118  * @brief アーティファクトの通常耐性を構造体に収める /
119  * Note an object's elemental brands
120  * @param o_ptr オブジェクト構造体の参照ポインタ
121  * @param resist_list 通常耐性構造体の参照ポインタ
122  * @return なし
123  */
124 static void analyze_resist(player_type *player_ptr, object_type *o_ptr, concptr *resist_list)
125 {
126     BIT_FLAGS flgs[TR_FLAG_SIZE];
127     object_flags(player_ptr, o_ptr, flgs);
128     resist_list = spoiler_flag_aux(flgs, resist_flags_desc, resist_list, N_ELEMENTS(resist_flags_desc));
129     *resist_list = NULL;
130 }
131
132 /*!
133  * @brief アーティファクトの免疫特性を構造体に収める /
134  * Note the immunities granted by an object
135  * @param o_ptr オブジェクト構造体の参照ポインタ
136  * @param immune_list 免疫構造体の参照ポインタ
137  * @return なし
138  */
139 static void analyze_immune(player_type *player_ptr, object_type *o_ptr, concptr *immune_list)
140 {
141     BIT_FLAGS flgs[TR_FLAG_SIZE];
142     object_flags(player_ptr, o_ptr, flgs);
143     immune_list = spoiler_flag_aux(flgs, immune_flags_desc, immune_list, N_ELEMENTS(immune_flags_desc));
144     *immune_list = NULL;
145 }
146
147 /*!
148  * @brief アーティファクトの維持特性を構造体に収める /
149  * Note which stats an object sustains
150  * @param o_ptr オブジェクト構造体の参照ポインタ
151  * @param sustain_list 維持特性構造体の参照ポインタ
152  * @return なし
153  */
154 static void analyze_sustains(player_type *player_ptr, object_type *o_ptr, concptr *sustain_list)
155 {
156     BIT_FLAGS flgs[TR_FLAG_SIZE];
157     object_flags(player_ptr, o_ptr, flgs);
158     if (have_flag(flgs, TR_SUST_STR) && have_flag(flgs, TR_SUST_INT) && have_flag(flgs, TR_SUST_WIS) && have_flag(flgs, TR_SUST_DEX)
159         && have_flag(flgs, TR_SUST_CON) && have_flag(flgs, TR_SUST_CHR)) {
160         *sustain_list++ = _("全能力", "All stats");
161     } else if (have_flag(flgs, TR_SUST_STR) || have_flag(flgs, TR_SUST_INT) || have_flag(flgs, TR_SUST_WIS) || have_flag(flgs, TR_SUST_DEX)
162         || have_flag(flgs, TR_SUST_CON) || have_flag(flgs, TR_SUST_CHR)) {
163         sustain_list = spoiler_flag_aux(flgs, sustain_flags_desc, sustain_list, N_ELEMENTS(sustain_flags_desc));
164     }
165
166     *sustain_list = NULL;
167 }
168
169 /*!
170  * @brief アーティファクトのその他の特性を構造体に収める /
171  * Note miscellaneous powers bestowed by an artifact such as see invisible,
172  * free action, permanent light, etc.
173  * @param o_ptr オブジェクト構造体の参照ポインタ
174  * @param misc_list その他の特性構造体の参照ポインタ
175  * @return なし
176  */
177 static void analyze_misc_magic(player_type *player_ptr, object_type *o_ptr, concptr *misc_list)
178 {
179     BIT_FLAGS flgs[TR_FLAG_SIZE];
180     char desc[256];
181
182     object_flags(player_ptr, o_ptr, flgs);
183     misc_list = spoiler_flag_aux(flgs, misc_flags2_desc, misc_list, N_ELEMENTS(misc_flags2_desc));
184     misc_list = spoiler_flag_aux(flgs, misc_flags3_desc, misc_list, N_ELEMENTS(misc_flags3_desc));
185     POSITION rad = 0;
186     if (have_flag(flgs, TR_LITE_1))
187         rad += 1;
188
189     if (have_flag(flgs, TR_LITE_2))
190         rad += 2;
191
192     if (have_flag(flgs, TR_LITE_3))
193         rad += 3;
194
195     if (have_flag(flgs, TR_LITE_M1))
196         rad -= 1;
197
198     if (have_flag(flgs, TR_LITE_M2))
199         rad -= 2;
200
201     if (have_flag(flgs, TR_LITE_M3))
202         rad -= 3;
203
204     if (o_ptr->name2 == EGO_LITE_SHINE)
205         rad++;
206
207     if (have_flag(flgs, TR_LITE_FUEL)) {
208         if (rad > 0)
209             sprintf(desc, _("それは燃料補給によって明かり(半径 %d)を授ける。", "It provides light (radius %d) when fueled."), (int)rad);
210     } else {
211         if (rad > 0)
212             sprintf(desc, _("永久光源(半径 %d)", "Permanent Light(radius %d)"), (int)rad);
213
214         if (rad < 0)
215             sprintf(desc, _("永久光源(半径-%d)。", "Permanent Light(radius -%d)"), (int)-rad);
216     }
217
218     if (rad != 0)
219         *misc_list++ = quark_str(quark_add(desc));
220
221     if (have_flag(flgs, TR_TY_CURSE))
222         *misc_list++ = _("太古の怨念", "Ancient Curse");
223
224     if (o_ptr->curse_flags & TRC_PERMA_CURSE)
225         *misc_list++ = _("永遠の呪い", "Permanently Cursed");
226     else if (o_ptr->curse_flags & TRC_HEAVY_CURSE)
227         *misc_list++ = _("強力な呪い", "Heavily Cursed");
228     else if (o_ptr->curse_flags & TRC_CURSED)
229         *misc_list++ = _("呪い", "Cursed");
230
231     if (have_flag(flgs, TR_ADD_L_CURSE))
232         *misc_list++ = _("呪いを増やす", "Cursing");
233
234     if (have_flag(flgs, TR_ADD_H_CURSE))
235         *misc_list++ = _("強力な呪いを増やす", "Heavily Cursing");
236
237     *misc_list = NULL;
238 }
239
240 /*!
241  * @brief アーティファクトの追加ランダム特性を構造体に収める /
242  * Note additional ability and/or resistance of fixed artifacts
243  * @param o_ptr オブジェクト構造体の参照ポインタ
244  * @param addition 追加ランダム耐性構造体の参照ポインタ
245  * @return なし
246  */
247 static void analyze_addition(object_type *o_ptr, char *addition)
248 {
249     artifact_type *a_ptr = &a_info[o_ptr->name1];
250     strcpy(addition, "");
251     if ((a_ptr->gen_flags & TRG_XTRA_POWER) && (a_ptr->gen_flags & TRG_XTRA_H_RES)) {
252         strcat(addition, _("能力and耐性", "Ability and Resistance"));
253         return;
254     }
255     
256     if (a_ptr->gen_flags & TRG_XTRA_POWER) {
257         strcat(addition, _("能力", "Ability"));
258         if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER)
259             strcat(addition, _("(1/2でand耐性)", "(plus Resistance about 1/2)"));
260
261         return;
262     }
263     
264     if (a_ptr->gen_flags & TRG_XTRA_H_RES) {
265         strcat(addition, _("耐性", "Resistance"));
266         if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER)
267             strcat(addition, _("(1/2でand能力)", "(plus Ability about 1/2)"));
268
269         return;
270     }
271     
272     if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER)
273         strcat(addition, _("能力or耐性", "Ability or Resistance"));
274 }
275
276 /*!
277  * @brief アーティファクトの基本情報を文字列に収める /
278  * Determine the minimum depth an artifact can appear, its rarity, its weight,
279  * and its value in gold pieces
280  * @param o_ptr オブジェクト構造体の参照ポインタ
281  * @param misc_desc 基本情報を収める文字列参照ポインタ
282  * @return なし
283  */
284 static void analyze_misc(object_type *o_ptr, char *misc_desc)
285 {
286     artifact_type *a_ptr = &a_info[o_ptr->name1];
287     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,
288         _(lbtokg1(a_ptr->weight), a_ptr->weight / 10), _(lbtokg2(a_ptr->weight), a_ptr->weight % 10), (long int)a_ptr->cost);
289 }
290
291 /*!
292  * @brief アーティファクトの情報全体を構造体に収める /
293  * Fill in an object description structure for a given object
294  * and its value in gold pieces
295  * @param player_ptr プレーヤーへの参照ポインタ
296  * @param o_ptr オブジェクト構造体の参照ポインタ
297  * @param desc_ptr 全アーティファクト情報を収める文字列参照ポインタ
298  * @return なし
299  */
300 void object_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(player_ptr, o_ptr, &desc_ptr->pval_info);
304     analyze_brand(player_ptr, o_ptr, desc_ptr->brands);
305     analyze_slay(player_ptr, o_ptr, desc_ptr->slays);
306     analyze_immune(player_ptr, o_ptr, desc_ptr->immunities);
307     analyze_resist(player_ptr, o_ptr, desc_ptr->resistances);
308     analyze_sustains(player_ptr, o_ptr, desc_ptr->sustains);
309     analyze_misc_magic(player_ptr, o_ptr, desc_ptr->misc_magic);
310     analyze_addition(o_ptr, desc_ptr->addition);
311     analyze_misc(o_ptr, desc_ptr->misc_desc);
312     desc_ptr->activation = activation_explanation(player_ptr, o_ptr);
313 }
314
315 /*!
316  * @brief ランダムアーティファクト1件を解析する /
317  * Fill in an object description structure for a given object
318  * @param player_ptr プレーヤーへの参照ポインタ
319  * @param o_ptr ランダムアーティファクトのオブジェクト構造体参照ポインタ
320  * @param desc_ptr 記述内容を収める構造体参照ポインタ
321  * @return なし
322  */
323 void random_artifact_analyze(player_type *player_ptr, object_type *o_ptr, obj_desc_list *desc_ptr)
324 {
325     analyze_general(player_ptr, o_ptr, desc_ptr->description);
326     analyze_pval(player_ptr, o_ptr, &desc_ptr->pval_info);
327     analyze_brand(player_ptr, o_ptr, desc_ptr->brands);
328     analyze_slay(player_ptr, o_ptr, desc_ptr->slays);
329     analyze_immune(player_ptr, o_ptr, desc_ptr->immunities);
330     analyze_resist(player_ptr, o_ptr, desc_ptr->resistances);
331     analyze_sustains(player_ptr, o_ptr, desc_ptr->sustains);
332     analyze_misc_magic(player_ptr, o_ptr, desc_ptr->misc_magic);
333     desc_ptr->activation = activation_explanation(player_ptr, o_ptr);
334     sprintf(desc_ptr->misc_desc, _("重さ %d.%d kg", "Weight %d.%d lbs"), _(lbtokg1(o_ptr->weight), o_ptr->weight / 10),
335         _(lbtokg2(o_ptr->weight), o_ptr->weight % 10));
336 }