OSDN Git Service

Merge branch 'develop' into macos-develop
[hengbandforosx/hengbandosx.git] / src / flavor / tval-description-switcher.cpp
1 /*!
2  * @brief 個々のアイテム種別について、未鑑定名/鑑定後の正式な名前を取得する処理
3  * @date 2020/07/07
4  * @author Hourier
5  */
6
7 #include "flavor/tval-description-switcher.h"
8 #include "flavor/flavor-util.h"
9 #include "flavor/object-flavor-types.h"
10 #include "locale/english.h"
11 #include "monster-race/monster-race.h"
12 #include "object-enchant/trg-types.h"
13 #include "object/tval-types.h"
14 #include "system/baseitem-info.h"
15 #include "system/item-entity.h"
16 #include "system/monster-race-info.h"
17 #include "util/bit-flags-calculator.h"
18 #include "util/enum-converter.h"
19 #ifdef JP
20 #else
21 #include "monster-race/race-flags1.h"
22 #include "player-info/class-info.h"
23 #endif
24
25 static std::pair<std::string, std::string> describe_monster_ball(const ItemEntity &item, const describe_option_type &opt)
26 {
27     const auto &basename = item.get_baseitem().name;
28     const auto r_idx = i2enum<MonsterRaceId>(item.pval);
29     auto *r_ptr = &monraces_info[r_idx];
30     if (!opt.known) {
31         return { basename, "" };
32     }
33
34     if (!MonsterRace(r_idx).is_valid()) {
35         return { basename, _(" (空)", " (empty)") };
36     }
37
38 #ifdef JP
39     const auto modstr = format(" (%s)", r_ptr->name.data());
40 #else
41     std::string modstr;
42     if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
43         modstr = format(" (%s%s)", (is_a_vowel(r_ptr->name[0]) ? "an " : "a "), r_ptr->name.data());
44     } else {
45         modstr = format(" (%s)", r_ptr->name.data());
46     }
47 #endif
48     return { basename, modstr };
49 }
50
51 static std::pair<std::string, std::string> describe_statue(const ItemEntity &item)
52 {
53     const auto &basename = item.get_baseitem().name;
54     const auto r_idx = i2enum<MonsterRaceId>(item.pval);
55     auto *r_ptr = &monraces_info[r_idx];
56 #ifdef JP
57     const auto &modstr = r_ptr->name;
58 #else
59     std::string modstr;
60     if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
61         modstr = format("%s%s", (is_a_vowel(r_ptr->name[0]) ? "an " : "a "), r_ptr->name.data());
62     } else {
63         modstr = r_ptr->name;
64     }
65 #endif
66     return { basename, modstr };
67 }
68
69 static std::pair<std::string, std::string> describe_corpse(const ItemEntity &item)
70 {
71     const auto r_idx = i2enum<MonsterRaceId>(item.pval);
72     auto *r_ptr = &monraces_info[r_idx];
73     const auto &modstr = r_ptr->name;
74 #ifdef JP
75     const auto basename = "#%";
76 #else
77     const auto basename =
78         (r_ptr->kind_flags.has(MonsterKindType::UNIQUE))
79             ? "& % of #"
80             : "& # %";
81 #endif
82     return { basename, modstr };
83 }
84
85 /*!
86  * @brief アイテムの未鑑定名を表す文字列を取得する
87  *
88  * 未鑑定名はゲーム開始時にシャッフルされるが、
89  * opt.mode の OD_FORCE_FLAVOR ビットが ON の場合シャッフルされていない未鑑定名を返す
90  * (未鑑定名からアイテムがバレるのを防ぐため、シンボルエディタで使用される)
91  * OFF の場合シャッフルされた未鑑定名を返す
92  *
93  * @param item 対象アイテムの ItemEntity オブジェクトへの参照
94  * @param opt アイテム表示オプション
95  * @return アイテムの未鑑定名を表す文字列
96  */
97 static std::string flavor_name_of(const ItemEntity &item, const describe_option_type &opt)
98 {
99     const auto &baseitem = item.get_baseitem();
100     return any_bits(opt.mode, OD_FORCE_FLAVOR)
101                ? baseitem.flavor_name
102                : baseitems_info[baseitem.flavor].flavor_name;
103 }
104
105 static std::pair<std::string, std::string> describe_amulet(const ItemEntity &item, const describe_option_type &opt)
106 {
107     const auto &baseitem = item.get_baseitem();
108     if (opt.aware && (item.is_fixed_artifact() || baseitem.gen_flags.has(ItemGenerationTraitType::INSTA_ART))) {
109         return { baseitem.name, "" };
110     }
111
112     if (!opt.flavor) {
113         return { _("%のアミュレット", "& Amulet~ of %"), "" };
114     } else if (opt.aware) {
115         return { _("%の#アミュレット", "& # Amulet~ of %"), flavor_name_of(item, opt) };
116     } else {
117         return { _("#アミュレット", "& # Amulet~"), flavor_name_of(item, opt) };
118     }
119 }
120
121 static std::pair<std::string, std::string> describe_ring(const ItemEntity &item, const describe_option_type &opt)
122 {
123     const auto &baseitem = item.get_baseitem();
124     if (opt.aware && (item.is_fixed_artifact() || baseitem.gen_flags.has(ItemGenerationTraitType::INSTA_ART))) {
125         return { baseitem.name, "" };
126     }
127
128     if (!opt.flavor) {
129         return { _("%の指輪", "& Ring~ of %"), "" };
130     } else if (opt.aware) {
131         return { _("%の#指輪", "& # Ring~ of %"), flavor_name_of(item, opt) };
132     } else {
133         return { _("#指輪", "& # Ring~"), flavor_name_of(item, opt) };
134     }
135 }
136
137 static std::pair<std::string, std::string> describe_staff(const ItemEntity &item, const describe_option_type &opt)
138 {
139     if (!opt.flavor) {
140         return { _("%の杖", "& Staff~ of %"), "" };
141     } else if (opt.aware) {
142         return { _("%の#杖", "& # Staff~ of %"), flavor_name_of(item, opt) };
143     } else {
144         return { _("#杖", "& # Staff~"), flavor_name_of(item, opt) };
145     }
146 }
147
148 static std::pair<std::string, std::string> describe_wand(const ItemEntity &item, const describe_option_type &opt)
149 {
150     if (!opt.flavor) {
151         return { _("%の魔法棒", "& Wand~ of %"), "" };
152     } else if (opt.aware) {
153         return { _("%の#魔法棒", "& # Wand~ of %"), flavor_name_of(item, opt) };
154     } else {
155         return { _("#魔法棒", "& # Wand~"), flavor_name_of(item, opt) };
156     }
157 }
158
159 static std::pair<std::string, std::string> describe_rod(const ItemEntity &item, const describe_option_type &opt)
160 {
161     if (!opt.flavor) {
162         return { _("%のロッド", "& Rod~ of %"), "" };
163     } else if (opt.aware) {
164         return { _("%の#ロッド", "& # Rod~ of %"), flavor_name_of(item, opt) };
165     } else {
166         return { _("#ロッド", "& # Rod~"), flavor_name_of(item, opt) };
167     }
168 }
169
170 static std::pair<std::string, std::string> describe_scroll(const ItemEntity &item, const describe_option_type &opt)
171 {
172     if (!opt.flavor) {
173         return { _("%の巻物", "& Scroll~ of %"), "" };
174     } else if (opt.aware) {
175         return { _("「#」と書かれた%の巻物", "& Scroll~ titled \"#\" of %"), flavor_name_of(item, opt) };
176     } else {
177         return { _("「#」と書かれた巻物", "& Scroll~ titled \"#\""), flavor_name_of(item, opt) };
178     }
179 }
180
181 static std::pair<std::string, std::string> describe_potion(const ItemEntity &item, const describe_option_type &opt)
182 {
183     if (!opt.flavor) {
184         return { _("%の薬", "& Potion~ of %"), "" };
185     } else if (opt.aware) {
186         return { _("%の#薬", "& # Potion~ of %"), flavor_name_of(item, opt) };
187     } else {
188         return { _("#薬", "& # Potion~"), flavor_name_of(item, opt) };
189     }
190 }
191
192 static std::pair<std::string, std::string> describe_food(const ItemEntity &item, const describe_option_type &opt)
193 {
194     const auto &baseitem = item.get_baseitem();
195     if (baseitem.flavor_name.empty()) {
196         return { baseitem.name, "" };
197     }
198
199     if (!opt.flavor) {
200         return { _("%のキノコ", "& Mushroom~ of %"), "" };
201     } else if (opt.aware) {
202         return { _("%の#キノコ", "& # Mushroom~ of %"), flavor_name_of(item, opt) };
203     } else {
204         return { _("#キノコ", "& # Mushroom~"), flavor_name_of(item, opt) };
205     }
206 }
207
208 static std::pair<std::string, std::string> describe_book_life()
209 {
210 #ifdef JP
211     return { "生命の魔法書%", "" };
212 #else
213     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
214         return { "& Book~ of Life Magic %", "" };
215     } else {
216         return { "& Life Spellbook~ %", "" };
217     }
218 #endif
219 }
220
221 static std::pair<std::string, std::string> describe_book_sorcery()
222 {
223 #ifdef JP
224     return { "仙術の魔法書%", "" };
225 #else
226     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
227         return { "& Book~ of Sorcery %", "" };
228     } else {
229         return { "& Sorcery Spellbook~ %", "" };
230     }
231 #endif
232 }
233
234 static std::pair<std::string, std::string> describe_book_nature()
235 {
236 #ifdef JP
237     return { "自然の魔法書%", "" };
238 #else
239     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
240         return { "& Book~ of Nature Magic %", "" };
241     } else {
242         return { "& Nature Spellbook~ %", "" };
243     }
244 #endif
245 }
246
247 static std::pair<std::string, std::string> describe_book_chaos()
248 {
249 #ifdef JP
250     return { "カオスの魔法書%", "" };
251 #else
252     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
253         return { "& Book~ of Chaos Magic %", "" };
254     } else {
255         return { "& Chaos Spellbook~ %", "" };
256     }
257 #endif
258 }
259
260 static std::pair<std::string, std::string> describe_book_death()
261 {
262 #ifdef JP
263     return { "暗黒の魔法書%", "" };
264 #else
265     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
266         return { "& Book~ of Death Magic %", "" };
267     } else {
268         return { "& Death Spellbook~ %", "" };
269     }
270 #endif
271 }
272
273 static std::pair<std::string, std::string> describe_book_trump()
274 {
275 #ifdef JP
276     return { "トランプの魔法書%", "" };
277 #else
278     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
279         return { "& Book~ of Trump Magic %", "" };
280     } else {
281         return { "& Trump Spellbook~ %", "" };
282     }
283 #endif
284 }
285
286 static std::pair<std::string, std::string> describe_book_arcane()
287 {
288 #ifdef JP
289     return { "秘術の魔法書%", "" };
290 #else
291     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
292         return { "& Book~ of Arcane Magic %", "" };
293     } else {
294         return { "& Arcane Spellbook~ %", "" };
295     }
296 #endif
297 }
298
299 static std::pair<std::string, std::string> describe_book_craft()
300 {
301 #ifdef JP
302     return { "匠の魔法書%", "" };
303 #else
304     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
305         return { "& Book~ of Craft Magic %", "" };
306     } else {
307         return { "& Craft Spellbook~ %", "" };
308     }
309 #endif
310 }
311
312 static std::pair<std::string, std::string> describe_book_demon()
313 {
314 #ifdef JP
315     return { "悪魔の魔法書%", "" };
316 #else
317     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
318         return { "& Book~ of Daemon Magic %", "" };
319     } else {
320         return { "& Daemon Spellbook~ %", "" };
321     }
322 #endif
323 }
324
325 static std::pair<std::string, std::string> describe_book_crusade()
326 {
327 #ifdef JP
328     return { "破邪の魔法書%", "" };
329 #else
330     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
331         return { "& Book~ of Crusade Magic %", "" };
332     } else {
333         return { "& Crusade Spellbook~ %", "" };
334     }
335 #endif
336 }
337
338 static std::pair<std::string, std::string> describe_book_hex()
339 {
340 #ifdef JP
341     return { "呪術の魔法書%", "" };
342 #else
343     if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK) {
344         return { "& Book~ of Hex Magic %", "" };
345     } else {
346         return { "& Hex Spellbook~ %", "" };
347     }
348 #endif
349 }
350
351 /*!
352  * @brief アイテムの tval に従う記述を得る
353  *
354  * アイテムの tval に従いベース名称(basename)と修正文字列(modstr)を得る。
355  * basename と modstr がどのような使われ方をするかは、describe_body() を参照。
356  *
357  * @param item アイテムへの参照
358  * @param opt 記述オプション
359  * @return std::pair<std::string, std::string> {basename, modstr} のペア
360  */
361 std::pair<std::string, std::string> switch_tval_description(const ItemEntity &item, const describe_option_type &opt)
362 {
363     const auto &basename = item.get_baseitem().name;
364
365     switch (item.bi_key.tval()) {
366     case ItemKindType::NONE:
367         return { _("(なし)", "(Nothing)"), "" };
368     case ItemKindType::SKELETON:
369     case ItemKindType::BOTTLE:
370     case ItemKindType::JUNK:
371     case ItemKindType::SPIKE:
372     case ItemKindType::FLASK:
373     case ItemKindType::CHEST:
374     case ItemKindType::WHISTLE:
375         return { basename, "" };
376     case ItemKindType::CAPTURE:
377         return describe_monster_ball(item, opt);
378     case ItemKindType::FIGURINE:
379     case ItemKindType::STATUE:
380         return describe_statue(item);
381     case ItemKindType::CORPSE:
382         return describe_corpse(item);
383     case ItemKindType::SHOT:
384     case ItemKindType::BOLT:
385     case ItemKindType::ARROW:
386     case ItemKindType::BOW:
387     case ItemKindType::HAFTED:
388     case ItemKindType::POLEARM:
389     case ItemKindType::SWORD:
390     case ItemKindType::DIGGING:
391     case ItemKindType::BOOTS:
392     case ItemKindType::GLOVES:
393     case ItemKindType::CLOAK:
394     case ItemKindType::CROWN:
395     case ItemKindType::HELM:
396     case ItemKindType::SHIELD:
397     case ItemKindType::SOFT_ARMOR:
398     case ItemKindType::HARD_ARMOR:
399     case ItemKindType::DRAG_ARMOR:
400     case ItemKindType::LITE:
401         return { basename, "" };
402     case ItemKindType::AMULET:
403         return describe_amulet(item, opt);
404     case ItemKindType::RING:
405         return describe_ring(item, opt);
406     case ItemKindType::CARD:
407         return { basename, "" };
408     case ItemKindType::STAFF:
409         return describe_staff(item, opt);
410     case ItemKindType::WAND:
411         return describe_wand(item, opt);
412     case ItemKindType::ROD:
413         return describe_rod(item, opt);
414     case ItemKindType::SCROLL:
415         return describe_scroll(item, opt);
416     case ItemKindType::POTION:
417         return describe_potion(item, opt);
418     case ItemKindType::FOOD:
419         return describe_food(item, opt);
420     case ItemKindType::PARCHMENT:
421         return { _("羊皮紙 - %", "& Parchment~ - %"), "" };
422     case ItemKindType::LIFE_BOOK:
423         return describe_book_life();
424     case ItemKindType::SORCERY_BOOK:
425         return describe_book_sorcery();
426     case ItemKindType::NATURE_BOOK:
427         return describe_book_nature();
428     case ItemKindType::CHAOS_BOOK:
429         return describe_book_chaos();
430     case ItemKindType::DEATH_BOOK:
431         return describe_book_death();
432     case ItemKindType::TRUMP_BOOK:
433         return describe_book_trump();
434     case ItemKindType::ARCANE_BOOK:
435         return describe_book_arcane();
436     case ItemKindType::CRAFT_BOOK:
437         return describe_book_craft();
438     case ItemKindType::DEMON_BOOK:
439         return describe_book_demon();
440     case ItemKindType::CRUSADE_BOOK:
441         return describe_book_crusade();
442     case ItemKindType::MUSIC_BOOK:
443         return { _("歌集%", "& Song Book~ %"), "" };
444     case ItemKindType::HISSATSU_BOOK:
445         return { _("& 武芸の書%", "Book~ of Kendo %"), "" };
446     case ItemKindType::HEX_BOOK:
447         return describe_book_hex();
448     case ItemKindType::GOLD:
449         return { basename, "" };
450     default:
451         return { _("(なし)", "(nothing)"), "" };
452     }
453 }