OSDN Git Service

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