OSDN Git Service

Merge branch 'Feature/Fix-Fall-Horse' into develop/3.0.0.1Alpha
[hengband/hengband.git] / src / flavor / named-item-describer.c
1 #include "flavor/named-item-describer.h"
2 #include "flavor/flavor-util.h"
3 #include "flavor/object-flavor-types.h"
4 #include "flavor/tval-description-switcher.h"
5 #include "game-option/text-display-options.h"
6 #include "mind/mind-weaponsmith.h"
7 #include "object-enchant/object-ego.h"
8 #include "object-enchant/special-object-flags.h"
9 #include "object-enchant/tr-types.h"
10 #include "object-hook/hook-enchant.h"
11 #include "object/object-flags.h"
12 #include "perception/object-perception.h"
13 #include "system/artifact-type-definition.h"
14 #include "util/bit-flags-calculator.h"
15 #include "util/quarks.h"
16 #include "util/string-processor.h"
17 #ifdef JP
18 #else
19 #include "locale/english.h"
20 #include "monster-race/monster-race.h"
21 #include "monster-race/race-flags1.h"
22 #endif
23
24 static void check_object_known_aware(player_type *player_ptr, flavor_type *flavor_ptr)
25 {
26     object_flags(player_ptr, flavor_ptr->o_ptr, flavor_ptr->tr_flags);
27     if (object_is_aware(flavor_ptr->o_ptr))
28         flavor_ptr->aware = TRUE;
29
30     if (object_is_known(flavor_ptr->o_ptr))
31         flavor_ptr->known = TRUE;
32
33     if (flavor_ptr->aware && ((flavor_ptr->mode & OD_NO_FLAVOR) || plain_descriptions))
34         flavor_ptr->flavor = FALSE;
35
36     if ((flavor_ptr->mode & OD_STORE) || (flavor_ptr->o_ptr->ident & IDENT_STORE)) {
37         flavor_ptr->flavor = FALSE;
38         flavor_ptr->aware = TRUE;
39         flavor_ptr->known = TRUE;
40     }
41
42     if (flavor_ptr->mode & OD_FORCE_FLAVOR) {
43         flavor_ptr->aware = FALSE;
44         flavor_ptr->flavor = TRUE;
45         flavor_ptr->known = FALSE;
46         flavor_ptr->flavor_k_ptr = flavor_ptr->k_ptr;
47     }
48 }
49
50 static void set_base_name(flavor_type *flavor_ptr)
51 {
52     if (!flavor_ptr->aware || !has_flag(flavor_ptr->tr_flags, TR_FULL_NAME))
53         return;
54
55     flavor_ptr->basenm = (flavor_ptr->known && (flavor_ptr->o_ptr->name1 != 0)) ? a_name + a_info[flavor_ptr->o_ptr->name1].name : flavor_ptr->kindname;
56 }
57
58 #ifdef JP
59 static void describe_prefix_ja(flavor_type *flavor_ptr)
60 {
61     flavor_ptr->s = flavor_ptr->basenm[0] == '&' ? flavor_ptr->basenm + 2 : flavor_ptr->basenm;
62     if (flavor_ptr->mode & OD_OMIT_PREFIX)
63         return;
64
65     if (flavor_ptr->o_ptr->number > 1) {
66         flavor_ptr->t = object_desc_count_japanese(flavor_ptr->t, flavor_ptr->o_ptr);
67         flavor_ptr->t = object_desc_str(flavor_ptr->t, "の ");
68     }
69 }
70
71 /*!
72  * @brief アーティファクトの表記処理
73  * @param アイテム表記への参照ポインタ
74  * @return なし
75  * @details 英語の場合アーティファクトは The が付くので分かるが、日本語では分からないのでマークをつける.
76  */
77 static void describe_artifact_prefix_ja(flavor_type *flavor_ptr)
78 {
79     if (!flavor_ptr->known)
80         return;
81
82     if (object_is_fixed_artifact(flavor_ptr->o_ptr))
83         flavor_ptr->t = object_desc_str(flavor_ptr->t, "★");
84     else if (flavor_ptr->o_ptr->art_name)
85         flavor_ptr->t = object_desc_str(flavor_ptr->t, "☆");
86 }
87
88 /*!
89  * @brief アーティファクトの説明表記
90  * @param flavor_ptr アイテム表記への参照ポインタ
91  * @return なし
92  * @details ランダムアーティファクト、固定アーティファクト、エゴの順に評価する
93  */
94 static void describe_artifact_ja(flavor_type *flavor_ptr)
95 {
96     if (!flavor_ptr->known)
97         return;
98
99     if (flavor_ptr->o_ptr->art_name) {
100         concptr temp = quark_str(flavor_ptr->o_ptr->art_name);
101
102         /* '『' から始まらない伝説のアイテムの名前は最初に付加する */
103         /* 英語版のセーブファイルから来た 'of XXX' は,「XXXの」と表示する */
104         if (strncmp(temp, "of ", 3) == 0) {
105             flavor_ptr->t = object_desc_str(flavor_ptr->t, &temp[3]);
106             flavor_ptr->t = object_desc_str(flavor_ptr->t, "の");
107         } else if ((strncmp(temp, "『", 2) != 0) && (strncmp(temp, "《", 2) != 0) && (temp[0] != '\''))
108             flavor_ptr->t = object_desc_str(flavor_ptr->t, temp);
109
110         return;
111     }
112
113     if (flavor_ptr->o_ptr->name1 && !has_flag(flavor_ptr->tr_flags, TR_FULL_NAME)) {
114         artifact_type *a_ptr = &a_info[flavor_ptr->o_ptr->name1];
115         /* '『' から始まらない伝説のアイテムの名前は最初に付加する */
116         if (strncmp(a_name + a_ptr->name, "『", 2) != 0)
117             flavor_ptr->t = object_desc_str(flavor_ptr->t, a_name + a_ptr->name);
118
119         return;
120     }
121
122     if (object_is_ego(flavor_ptr->o_ptr)) {
123         ego_item_type *e_ptr = &e_info[flavor_ptr->o_ptr->name2];
124         flavor_ptr->t = object_desc_str(flavor_ptr->t, e_name + e_ptr->name);
125     }
126 }
127
128 /*!
129  * @brief ランダムアーティファクトの表記
130  * @param flavor_ptr アイテム表記への参照ポインタ
131  * @return ランダムアーティファクトならTRUE、違うならFALSE
132  * @details ランダムアーティファクトの名前はセーブファイルに記録されるので、英語版の名前もそれらしく変換する.
133  */
134 static bool describe_random_artifact_body_ja(flavor_type *flavor_ptr)
135 {
136     if (flavor_ptr->o_ptr->art_name == 0)
137         return FALSE;
138
139     char temp[256];
140     int itemp;
141     strcpy(temp, quark_str(flavor_ptr->o_ptr->art_name));
142     if (strncmp(temp, "『", 2) == 0 || strncmp(temp, "《", 2) == 0) {
143         flavor_ptr->t = object_desc_str(flavor_ptr->t, temp);
144         return TRUE;
145     }
146
147     if (temp[0] != '\'')
148         return TRUE;
149
150     itemp = strlen(temp);
151     temp[itemp - 1] = 0;
152     flavor_ptr->t = object_desc_str(flavor_ptr->t, "『");
153     flavor_ptr->t = object_desc_str(flavor_ptr->t, &temp[1]);
154     flavor_ptr->t = object_desc_str(flavor_ptr->t, "』");
155     return TRUE;
156 }
157
158 static void describe_ego_body_ja(flavor_type *flavor_ptr)
159 {
160     if (!flavor_ptr->o_ptr->inscription)
161         return;
162
163     concptr str = quark_str(flavor_ptr->o_ptr->inscription);
164     while (*str) {
165         if (iskanji(*str)) {
166             str += 2;
167             continue;
168         }
169
170         if (*str == '#')
171             break;
172
173         str++;
174     }
175
176     if (*str == '\0')
177         return;
178
179     concptr str_aux = angband_strchr(quark_str(flavor_ptr->o_ptr->inscription), '#');
180     flavor_ptr->t = object_desc_str(flavor_ptr->t, "『");
181     flavor_ptr->t = object_desc_str(flavor_ptr->t, &str_aux[1]);
182     flavor_ptr->t = object_desc_str(flavor_ptr->t, "』");
183 }
184
185 /*!
186  * @brief アーティファクトのアイテム名を表記する
187  * @param flavor_ptr アイテム表記への参照ポインタ
188  * @return なし
189  * @details '『'から始まる伝説のアイテムの名前は最後に付加する
190  */
191 static void describe_artifact_body_ja(flavor_type *flavor_ptr)
192 {
193     if (!flavor_ptr->known)
194         return;
195
196     if (describe_random_artifact_body_ja(flavor_ptr))
197         return;
198
199     if (object_is_fixed_artifact(flavor_ptr->o_ptr)) {
200         artifact_type *a_ptr = &a_info[flavor_ptr->o_ptr->name1];
201         if (strncmp(a_name + a_ptr->name, "『", 2) == 0)
202             flavor_ptr->t = object_desc_str(flavor_ptr->t, a_name + a_ptr->name);
203
204         return;
205     }
206
207     describe_ego_body_ja(flavor_ptr);
208 }
209 #else
210
211 static void describe_vowel(flavor_type *flavor_ptr)
212 {
213     bool vowel;
214     switch (*flavor_ptr->s) {
215     case '#':
216         vowel = is_a_vowel(flavor_ptr->modstr[0]);
217         break;
218     case '%':
219         vowel = is_a_vowel(*flavor_ptr->kindname);
220         break;
221     default:
222         vowel = is_a_vowel(*flavor_ptr->s);
223         break;
224     }
225
226     if (vowel)
227         flavor_ptr->t = object_desc_str(flavor_ptr->t, "an ");
228     else
229         flavor_ptr->t = object_desc_str(flavor_ptr->t, "a ");
230 }
231
232 /*!
233  * @brief 0個、1個、2個以上の時に個数を書き分ける処理 / Process to write the number when there are 0, 1, or 2 or more.
234  * @param flavor_ptr アイテム表記への参照ポインタ / Reference pointer to item's flavor
235  * @return 1個ならFALSE、0または2個以上ならTRUE / If the number of items is 1, then FALE is returned, and if 0 or 2 or more, then TRUE is returned
236  * @details 1個なら後続処理実行 / If the number of items is 1, then the continuous process will be run.
237  */
238 static bool describe_prefix_en(flavor_type *flavor_ptr)
239 {
240     if (flavor_ptr->o_ptr->number <= 0) {
241         flavor_ptr->t = object_desc_str(flavor_ptr->t, "no more ");
242         return TRUE;
243     }
244
245     if (flavor_ptr->o_ptr->number == 1)
246         return FALSE;
247
248     flavor_ptr->t = object_desc_num(flavor_ptr->t, flavor_ptr->o_ptr->number);
249     flavor_ptr->t = object_desc_chr(flavor_ptr->t, ' ');
250     return TRUE;
251 }
252
253 static void describe_artifact_prefix_en(flavor_type *flavor_ptr)
254 {
255     flavor_ptr->s = flavor_ptr->basenm + 2;
256     if (flavor_ptr->mode & OD_OMIT_PREFIX)
257         return;
258
259     if (describe_prefix_en(flavor_ptr))
260         return;
261
262     if ((flavor_ptr->known && object_is_artifact(flavor_ptr->o_ptr))
263         || ((flavor_ptr->o_ptr->tval == TV_CORPSE) && (r_info[flavor_ptr->o_ptr->pval].flags1 & RF1_UNIQUE))) {
264         flavor_ptr->t = object_desc_str(flavor_ptr->t, "The ");
265         return;
266     }
267
268     describe_vowel(flavor_ptr);
269 }
270
271 static void describe_basename_en(flavor_type *flavor_ptr)
272 {
273     flavor_ptr->s = flavor_ptr->basenm;
274     if (flavor_ptr->mode & OD_OMIT_PREFIX)
275         return;
276
277     if (describe_prefix_en(flavor_ptr))
278         return;
279
280     if (flavor_ptr->known && object_is_artifact(flavor_ptr->o_ptr))
281         flavor_ptr->t = object_desc_str(flavor_ptr->t, "The ");
282 }
283
284 static void describe_artifact_body_en(flavor_type *flavor_ptr)
285 {
286     if (!flavor_ptr->known || has_flag(flavor_ptr->tr_flags, TR_FULL_NAME))
287         return;
288
289     if (flavor_ptr->o_ptr->art_name) {
290         flavor_ptr->t = object_desc_chr(flavor_ptr->t, ' ');
291         flavor_ptr->t = object_desc_str(flavor_ptr->t, quark_str(flavor_ptr->o_ptr->art_name));
292         return;
293     }
294
295     if (object_is_fixed_artifact(flavor_ptr->o_ptr)) {
296         artifact_type *a_ptr = &a_info[flavor_ptr->o_ptr->name1];
297         flavor_ptr->t = object_desc_chr(flavor_ptr->t, ' ');
298         flavor_ptr->t = object_desc_str(flavor_ptr->t, a_name + a_ptr->name);
299         return;
300     }
301
302     if (object_is_ego(flavor_ptr->o_ptr)) {
303         ego_item_type *e_ptr = &e_info[flavor_ptr->o_ptr->name2];
304         flavor_ptr->t = object_desc_chr(flavor_ptr->t, ' ');
305         flavor_ptr->t = object_desc_str(flavor_ptr->t, e_name + e_ptr->name);
306     }
307
308     if (flavor_ptr->o_ptr->inscription && angband_strchr(quark_str(flavor_ptr->o_ptr->inscription), '#')) {
309         concptr str = angband_strchr(quark_str(flavor_ptr->o_ptr->inscription), '#');
310         flavor_ptr->t = object_desc_chr(flavor_ptr->t, ' ');
311         flavor_ptr->t = object_desc_str(flavor_ptr->t, &str[1]);
312     }
313 }
314 #endif
315
316 /*!
317  * @brief 銘を表記する
318  * @param flavor_ptr アイテム表記への参照ポインタ
319  * @return なし
320  * @details ランダムアーティファクト、固定アーティファクト、エゴの順に評価する
321  */
322 static void describe_inscription(flavor_type *flavor_ptr)
323 {
324     for (flavor_ptr->s0 = NULL; *flavor_ptr->s || flavor_ptr->s0;) {
325         if (!*flavor_ptr->s) {
326             flavor_ptr->s = flavor_ptr->s0 + 1;
327             flavor_ptr->s0 = NULL;
328         } else if ((*flavor_ptr->s == '#') && !flavor_ptr->s0) {
329             flavor_ptr->s0 = flavor_ptr->s;
330             flavor_ptr->s = flavor_ptr->modstr;
331             flavor_ptr->modstr = "";
332         } else if ((*flavor_ptr->s == '%') && !flavor_ptr->s0) {
333             flavor_ptr->s0 = flavor_ptr->s;
334             flavor_ptr->s = flavor_ptr->kindname;
335             flavor_ptr->kindname = "";
336         }
337
338 #ifdef JP
339 #else
340         else if (*flavor_ptr->s == '~') {
341             if (!(flavor_ptr->mode & OD_NO_PLURAL) && (flavor_ptr->o_ptr->number != 1)) {
342                 char k = flavor_ptr->t[-1];
343                 if ((k == 's') || (k == 'h'))
344                     *flavor_ptr->t++ = 'e';
345
346                 *flavor_ptr->t++ = 's';
347             }
348
349             flavor_ptr->s++;
350         }
351 #endif
352         else
353             *flavor_ptr->t++ = *flavor_ptr->s++;
354     }
355 }
356
357 void describe_named_item(player_type *player_ptr, flavor_type *flavor_ptr)
358 {
359     check_object_known_aware(player_ptr, flavor_ptr);
360     switch_tval_description(flavor_ptr);
361     set_base_name(flavor_ptr);
362     flavor_ptr->t = flavor_ptr->tmp_val;
363 #ifdef JP
364     describe_prefix_ja(flavor_ptr);
365     describe_artifact_prefix_ja(flavor_ptr);
366 #else
367
368     if (flavor_ptr->basenm[0] == '&')
369         describe_artifact_prefix_en(flavor_ptr);
370     else
371         describe_basename_en(flavor_ptr);
372 #endif
373
374 #ifdef JP
375     if (object_is_smith(player_ptr, flavor_ptr->o_ptr))
376         flavor_ptr->t = object_desc_str(flavor_ptr->t, format("鍛冶師%sの", player_ptr->name));
377
378     describe_artifact_ja(flavor_ptr);
379 #endif
380
381     describe_inscription(flavor_ptr);
382     *flavor_ptr->t = '\0';
383
384 #ifdef JP
385     describe_artifact_body_ja(flavor_ptr);
386 #else
387     if (object_is_smith(player_ptr, flavor_ptr->o_ptr))
388         flavor_ptr->t = object_desc_str(flavor_ptr->t, format(" of %s the Smith", player_ptr->name));
389
390     describe_artifact_body_en(flavor_ptr);
391 #endif
392 }