OSDN Git Service

Merge pull request #1919 from sikabane-works/fearure/refactor-normal_traps
[hengbandforosx/hengbandosx.git] / src / flavor / flavor-util.cpp
1 #include "flavor/flavor-util.h"
2 #include "flavor/flag-inscriptions-table.h"
3 #include "object-enchant/object-ego.h"
4 #include "object-enchant/tr-types.h"
5 #include "object/object-flags.h"
6 #include "object/object-kind.h"
7 #include "perception/object-perception.h"
8 #include "sv-definition/sv-food-types.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/enum-converter.h"
13 #include "util/quarks.h"
14
15 flavor_type *initialize_flavor_type(flavor_type *flavor_ptr, char *buf, object_type *o_ptr, BIT_FLAGS mode)
16 {
17     flavor_ptr->buf = buf;
18     flavor_ptr->o_ptr = o_ptr;
19     flavor_ptr->mode = mode;
20     flavor_ptr->kindname = k_info[o_ptr->k_idx].name.c_str();
21     flavor_ptr->basenm = flavor_ptr->kindname;
22     flavor_ptr->modstr = "";
23     flavor_ptr->aware = false;
24     flavor_ptr->known = false;
25     flavor_ptr->flavor = true;
26     flavor_ptr->show_weapon = false;
27     flavor_ptr->show_armour = false;
28     flavor_ptr->p1 = '(';
29     flavor_ptr->p2 = ')';
30     flavor_ptr->b1 = '[';
31     flavor_ptr->b2 = ']';
32     flavor_ptr->c1 = '{';
33     flavor_ptr->c2 = '}';
34     flavor_ptr->k_ptr = &k_info[o_ptr->k_idx];
35     flavor_ptr->flavor_k_ptr = &k_info[flavor_ptr->k_ptr->flavor];
36     return flavor_ptr;
37 }
38
39 /*!
40  * @brief 対象文字配列に一文字だけをコピーする。
41  * @param t 保管先文字列ポインタ
42  * @param c 保管したい1文字
43  * @details
44  * Print a char "c" into a string "t", as if by sprintf(t, "%c", c),\n
45  * and return a pointer to the terminator (t + 1).\n
46  */
47 char *object_desc_chr(char *t, char c)
48 {
49     *t++ = c;
50     *t = '\0';
51     return t;
52 }
53
54 /*!
55  * @brief 対象文字配列に文字列をコピーする。
56  * @param t 保管先文字列ポインタ
57  * @param s コピーしたい文字列ポインタ
58  * @return 保管先の末尾アドレス
59  * @details
60  * Print a string "s" into a string "t", as if by strcpy(t, s),
61  * and return a pointer to the terminator.
62  */
63 char *object_desc_str(char *t, concptr s)
64 {
65     while (*s)
66         *t++ = *s++;
67
68     *t = '\0';
69     return t;
70 }
71
72 /*!
73  * @brief 対象文字配列に符号なし整数値をコピーする。
74  * @param t 保管先文字列ポインタ
75  * @param n コピーしたい数値
76  * @details
77  * Print an unsigned number "n" into a string "t", actually by
78  * sprintf(t, "%u", n), and return a pointer to the terminator.
79  */
80 char *object_desc_num(char *t, uint n)
81 {
82     int ret = sprintf(t, "%u", n);
83     if (ret < 0) {
84         // error
85         ret = 0;
86         *t = '\0';
87     }
88     return t + ret;
89 }
90
91 /*!
92  * @brief 対象文字配列に符号あり整数値をコピーする。
93  * @param t 保管先文字列ポインタ
94  * @param v コピーしたい数値
95  * @details
96  * Print an signed number "v" into a string "t", as if by
97  * sprintf(t, "%+d", n), and return a pointer to the terminator.
98  * Note that we always print a sign, either "+" or "-".
99  */
100 char *object_desc_int(char *t, int v)
101 {
102     uint p, n;
103     if (v < 0) {
104         n = 0 - v;
105         *t++ = '-';
106     } else {
107         n = v;
108         *t++ = '+';
109     }
110
111     /* loop */
112     for (p = 1; n >= p * 10; p = p * 10)
113         ;
114
115     while (p >= 1) {
116         *t++ = '0' + n / p;
117         n = n % p;
118         p = p / 10;
119     }
120
121     *t = '\0';
122     return t;
123 }
124
125 /*!
126  * @brief オブジェクトフラグを追加する
127  * @param short_flavor フラグの短縮表現 (反魔法/アンチテレポの"["、耐性の"r"、耐混乱の"乱" 等)
128  * @param ptr 特性短縮表記を格納する文字列ポインタ
129  */
130 static void add_inscription(char **short_flavor, concptr str) { *short_flavor = object_desc_str(*short_flavor, str); }
131
132 /*!
133  * @brief get_inscriptionのサブセットとしてオブジェクトの特性フラグを返す / Helper function for get_inscription()
134  * @param fi_vec 参照する特性表示記号テーブル
135  * @param flgs 対応するオブジェクトのフラグ文字列
136  * @param kanji TRUEならば漢字記述/FALSEならば英語記述
137  * @param ptr フラグ群を保管する文字列参照ポインタ
138  * @return フラグ群を保管する文字列参照ポインタ(ptrと同じ)
139  * @details
140  * Print an signed number "v" into a string "t", as if by
141  * sprintf(t, "%+d", n), and return a pointer to the terminator.
142  * Note that we always print a sign, either "+" or "-".
143  */
144 static char *inscribe_flags_aux(std::vector<flag_insc_table> &fi_vec, const TrFlags &flgs, bool kanji, char *ptr)
145 {
146 #ifdef JP
147 #else
148     (void)kanji;
149 #endif
150
151     for (flag_insc_table &fi : fi_vec)
152         if (flgs.has(fi.flag) && (fi.except_flag == -1 || flgs.has_not(i2enum<tr_type>(fi.except_flag))))
153             add_inscription(&ptr, _(kanji ? fi.japanese : fi.english, fi.english));
154
155     return ptr;
156 }
157
158 /*!
159  * @brief オブジェクトの特性表示記号テーブル1つに従いオブジェクトの特性フラグ配列に1つでも該当の特性があるかを返す / Special variation of has_flag for
160  * auto-inscription
161  * @param fi_vec 参照する特性表示記号テーブル
162  * @param flgs 対応するオブジェクトのフラグ文字列
163  * @return 1つでも該当の特性があったらTRUEを返す。
164  */
165 static bool has_flag_of(std::vector<flag_insc_table> &fi_vec, const TrFlags &flgs)
166 {
167     for (flag_insc_table &fi : fi_vec)
168         if (flgs.has(fi.flag) && (fi.except_flag == -1 || flgs.has_not(i2enum<tr_type>(fi.except_flag))))
169             return true;
170
171     return false;
172 }
173
174 /*!
175  * @brief オブジェクト名の特性短縮表記をまとめて提示する。
176  * @param short_flavor 特性短縮表記を格納する文字列ポインタ
177  * @param o_ptr 特性短縮表記を得たいオブジェクト構造体の参照ポインタ
178  * @param kanji TRUEならば漢字表記 / FALSEなら英語表記
179  * @param all TRUEならばベースアイテム上で明らかなフラグは省略する
180  * @return ptrと同じアドレス
181  */
182 char *get_ability_abbreviation(char *short_flavor, object_type *o_ptr, bool kanji, bool all)
183 {
184     char *prev_ptr = short_flavor;
185     auto flgs = object_flags(o_ptr);
186     if (!all) {
187         object_kind *k_ptr = &k_info[o_ptr->k_idx];
188         flgs.reset(k_ptr->flags);
189
190         if (o_ptr->is_fixed_artifact()) {
191             artifact_type *a_ptr = &a_info[o_ptr->name1];
192             flgs.reset(a_ptr->flags);
193         }
194
195         if (o_ptr->is_ego()) {
196             ego_item_type *e_ptr = &e_info[o_ptr->name2];
197             flgs.reset(e_ptr->flags);
198         }
199     }
200
201     if (has_dark_flag(flgs)) {
202         if (flgs.has(TR_LITE_1))
203             flgs.reset(TR_LITE_1);
204
205         if (flgs.has(TR_LITE_2))
206             flgs.reset(TR_LITE_2);
207
208         if (flgs.has(TR_LITE_3))
209             flgs.reset(TR_LITE_3);
210     } else if (has_lite_flag(flgs)) {
211         flgs.set(TR_LITE_1);
212         if (flgs.has(TR_LITE_2))
213             flgs.reset(TR_LITE_2);
214
215         if (flgs.has(TR_LITE_3))
216             flgs.reset(TR_LITE_3);
217     }
218
219     if (has_flag_of(flag_insc_plus, flgs) && kanji)
220         add_inscription(&short_flavor, "+");
221
222     short_flavor = inscribe_flags_aux(flag_insc_plus, flgs, kanji, short_flavor);
223
224     if (has_flag_of(flag_insc_immune, flgs)) {
225         if (!kanji && short_flavor != prev_ptr) {
226             add_inscription(&short_flavor, ";");
227             prev_ptr = short_flavor;
228         }
229
230         add_inscription(&short_flavor, "*");
231     }
232
233     short_flavor = inscribe_flags_aux(flag_insc_immune, flgs, kanji, short_flavor);
234
235     if (has_flag_of(flag_insc_vuln, flgs)) {
236         if (!kanji && short_flavor != prev_ptr) {
237             add_inscription(&short_flavor, ";");
238             prev_ptr = short_flavor;
239         }
240
241         add_inscription(&short_flavor, "v");
242     }
243
244     short_flavor = inscribe_flags_aux(flag_insc_vuln, flgs, kanji, short_flavor);
245
246     if (has_flag_of(flag_insc_resistance, flgs)) {
247         if (kanji)
248             add_inscription(&short_flavor, "r");
249         else if (short_flavor != prev_ptr) {
250             add_inscription(&short_flavor, ";");
251             prev_ptr = short_flavor;
252         }
253     }
254
255     short_flavor = inscribe_flags_aux(flag_insc_resistance, flgs, kanji, short_flavor);
256
257     if (has_flag_of(flag_insc_misc, flgs) && (short_flavor != prev_ptr)) {
258         add_inscription(&short_flavor, ";");
259         prev_ptr = short_flavor;
260     }
261
262     short_flavor = inscribe_flags_aux(flag_insc_misc, flgs, kanji, short_flavor);
263
264     if (has_flag_of(flag_insc_aura, flgs))
265         add_inscription(&short_flavor, "[");
266
267     short_flavor = inscribe_flags_aux(flag_insc_aura, flgs, kanji, short_flavor);
268
269     if (has_flag_of(flag_insc_brand, flgs))
270         add_inscription(&short_flavor, "|");
271
272     short_flavor = inscribe_flags_aux(flag_insc_brand, flgs, kanji, short_flavor);
273
274     if (has_flag_of(flag_insc_kill, flgs))
275         add_inscription(&short_flavor, "/X");
276
277     short_flavor = inscribe_flags_aux(flag_insc_kill, flgs, kanji, short_flavor);
278
279     if (has_flag_of(flag_insc_slay, flgs))
280         add_inscription(&short_flavor, "/");
281
282     short_flavor = inscribe_flags_aux(flag_insc_slay, flgs, kanji, short_flavor);
283
284     if (kanji) {
285         if (has_flag_of(flag_insc_esp1, flgs) || has_flag_of(flag_insc_esp2, flgs))
286             add_inscription(&short_flavor, "~");
287
288         short_flavor = inscribe_flags_aux(flag_insc_esp1, flgs, kanji, short_flavor);
289         short_flavor = inscribe_flags_aux(flag_insc_esp2, flgs, kanji, short_flavor);
290     } else {
291         if (has_flag_of(flag_insc_esp1, flgs))
292             add_inscription(&short_flavor, "~");
293
294         short_flavor = inscribe_flags_aux(flag_insc_esp1, flgs, kanji, short_flavor);
295
296         if (has_flag_of(flag_insc_esp2, flgs))
297             add_inscription(&short_flavor, "~");
298
299         short_flavor = inscribe_flags_aux(flag_insc_esp2, flgs, kanji, short_flavor);
300     }
301
302     if (has_flag_of(flag_insc_sust, flgs))
303         add_inscription(&short_flavor, "(");
304
305     short_flavor = inscribe_flags_aux(flag_insc_sust, flgs, kanji, short_flavor);
306     *short_flavor = '\0';
307     return short_flavor;
308 }
309
310 /*!
311  * @brief オブジェクト名の特性短縮表記+刻み内容を提示する。 / Get object inscription with auto inscription of object flags.
312  * @param buff 特性短縮表記を格納する文字列ポインタ
313  * @param o_ptr 特性短縮表記を得たいオブジェクト構造体の参照ポインタ
314  */
315 void get_inscription(char *buff, object_type *o_ptr)
316 {
317     concptr insc = quark_str(o_ptr->inscription);
318     char *ptr = buff;
319     if (!o_ptr->is_fully_known()) {
320         while (*insc) {
321             if (*insc == '#')
322                 break;
323 #ifdef JP
324             if (iskanji(*insc))
325                 *buff++ = *insc++;
326 #endif
327             *buff++ = *insc++;
328         }
329
330         *buff = '\0';
331         return;
332     }
333
334     *buff = '\0';
335     for (; *insc; insc++) {
336         if (*insc == '#')
337             break;
338         else if ('%' == *insc) {
339             bool kanji = false;
340             bool all;
341             concptr start = ptr;
342             if (ptr >= buff + MAX_NLEN)
343                 continue;
344
345 #ifdef JP
346             if ('%' == insc[1]) {
347                 insc++;
348                 kanji = false;
349             } else
350                 kanji = true;
351 #endif
352
353             if ('a' == insc[1] && 'l' == insc[2] && 'l' == insc[3]) {
354                 all = true;
355                 insc += 3;
356             } else
357                 all = false;
358
359             ptr = get_ability_abbreviation(ptr, o_ptr, kanji, all);
360             if (ptr == start)
361                 add_inscription(&ptr, " ");
362         } else
363             *ptr++ = *insc;
364     }
365
366     *ptr = '\0';
367 }
368
369 #ifdef JP
370 /*!
371  * @brief 日本語の個数表示ルーチン
372  * @param t 保管先文字列ポインタ
373  * @param o_ptr 記述したいオブジェクトの構造体参照ポインタ
374  * @details
375  * cmd1.c で流用するために object_desc_japanese から移動した。
376  */
377 char *object_desc_count_japanese(char *t, object_type *o_ptr)
378 {
379     t = object_desc_num(t, o_ptr->number);
380     switch (o_ptr->tval) {
381     case ItemKindType::BOLT:
382     case ItemKindType::ARROW:
383     case ItemKindType::POLEARM:
384     case ItemKindType::STAFF:
385     case ItemKindType::WAND:
386     case ItemKindType::ROD:
387     case ItemKindType::DIGGING: {
388         t = object_desc_str(t, "本");
389         break;
390     }
391     case ItemKindType::SCROLL: {
392         t = object_desc_str(t, "巻");
393         break;
394     }
395     case ItemKindType::POTION: {
396         t = object_desc_str(t, "服");
397         break;
398     }
399     case ItemKindType::LIFE_BOOK:
400     case ItemKindType::SORCERY_BOOK:
401     case ItemKindType::NATURE_BOOK:
402     case ItemKindType::CHAOS_BOOK:
403     case ItemKindType::DEATH_BOOK:
404     case ItemKindType::TRUMP_BOOK:
405     case ItemKindType::ARCANE_BOOK:
406     case ItemKindType::CRAFT_BOOK:
407     case ItemKindType::DEMON_BOOK:
408     case ItemKindType::CRUSADE_BOOK:
409     case ItemKindType::MUSIC_BOOK:
410     case ItemKindType::HISSATSU_BOOK:
411     case ItemKindType::HEX_BOOK: {
412         t = object_desc_str(t, "冊");
413         break;
414     }
415     case ItemKindType::SOFT_ARMOR:
416     case ItemKindType::HARD_ARMOR:
417     case ItemKindType::DRAG_ARMOR:
418     case ItemKindType::CLOAK: {
419         t = object_desc_str(t, "着");
420         break;
421     }
422     case ItemKindType::SWORD:
423     case ItemKindType::HAFTED:
424     case ItemKindType::BOW: {
425         t = object_desc_str(t, "振");
426         break;
427     }
428     case ItemKindType::BOOTS: {
429         t = object_desc_str(t, "足");
430         break;
431     }
432     case ItemKindType::CARD: {
433         t = object_desc_str(t, "枚");
434         break;
435     }
436     case ItemKindType::FOOD: {
437         if (o_ptr->sval == SV_FOOD_JERKY) {
438             t = object_desc_str(t, "切れ");
439             break;
440         }
441     }
442         /* Fall through */
443     default: {
444         if (o_ptr->number < 10) {
445             t = object_desc_str(t, "つ");
446         } else {
447             t = object_desc_str(t, "個");
448         }
449         break;
450     }
451     }
452     return t;
453 }
454 #endif
455
456 bool has_lite_flag(const TrFlags &flags)
457 {
458     return flags.has(TR_LITE_1) || flags.has(TR_LITE_2) || flags.has(TR_LITE_3);
459 }
460
461 bool has_dark_flag(const TrFlags &flags)
462 {
463     return flags.has(TR_LITE_M1) || flags.has(TR_LITE_M2) || flags.has(TR_LITE_M3);
464 }