OSDN Git Service

[Refactor] #2645 strip_name() の戻り値をvoid からstd::string に変更し、引数からchar* を消した
[hengbandforosx/hengbandosx.git] / src / flavor / object-flavor.cpp
1 /*!
2  *  @brief オブジェクトの記述処理 / Mbject flavor code
3  *  @date 2014/01/03
4  *  @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
6  *\n
7  * This software may be copied and distributed for educational, research,\n
8  * and not for profit purposes provided that this copyright and statement\n
9  * are included in all such copies.  Other copyrights may also apply.\n
10  */
11
12 #include "flavor/object-flavor.h"
13 #include "combat/shoot.h"
14 #include "flavor/flag-inscriptions-table.h"
15 #include "flavor/flavor-util.h"
16 #include "flavor/object-flavor-types.h"
17 #include "game-option/text-display-options.h"
18 #include "grid/trap.h"
19 #include "inventory/inventory-slot-types.h"
20 #include "io/files-util.h"
21 #include "locale/english.h"
22 #include "locale/japanese.h"
23 #include "mind/mind-sniper.h"
24 #include "mind/mind-weaponsmith.h"
25 #include "monster-race/monster-race.h"
26 #include "monster-race/race-flags1.h"
27 #include "object-enchant/object-ego.h"
28 #include "object-enchant/special-object-flags.h"
29 #include "object-enchant/tr-types.h"
30 #include "object-enchant/trg-types.h"
31 #include "object-hook/hook-quest.h"
32 #include "object/object-flags.h"
33 #include "object/object-info.h"
34 #include "object/object-kind.h"
35 #include "perception/object-perception.h"
36 #include "player-info/class-info.h"
37 #include "player/player-status.h"
38 #include "sv-definition/sv-food-types.h"
39 #include "sv-definition/sv-lite-types.h"
40 #include "util/bit-flags-calculator.h"
41 #include "util/quarks.h"
42 #include "util/string-processor.h"
43 #include "world/world.h"
44 #include <functional>
45 #include <sstream>
46 #include <utility>
47
48 /*!
49  * @brief 最初から簡易な名称が明らかになるベースアイテムの判定。 /  Certain items, if aware, are known instantly
50  * @param i ベースアイテムID
51  * @return 簡易名称を明らかにするならTRUEを返す。
52  * @details
53  * This function is used only by "flavor_init()"
54  */
55 static bool object_easy_know(int i)
56 {
57     auto *k_ptr = &k_info[i];
58     switch (k_ptr->tval) {
59     case ItemKindType::LIFE_BOOK:
60     case ItemKindType::SORCERY_BOOK:
61     case ItemKindType::NATURE_BOOK:
62     case ItemKindType::CHAOS_BOOK:
63     case ItemKindType::DEATH_BOOK:
64     case ItemKindType::TRUMP_BOOK:
65     case ItemKindType::ARCANE_BOOK:
66     case ItemKindType::CRAFT_BOOK:
67     case ItemKindType::DEMON_BOOK:
68     case ItemKindType::CRUSADE_BOOK:
69     case ItemKindType::MUSIC_BOOK:
70     case ItemKindType::HISSATSU_BOOK:
71     case ItemKindType::HEX_BOOK:
72         return true;
73     case ItemKindType::FLASK:
74     case ItemKindType::JUNK:
75     case ItemKindType::BOTTLE:
76     case ItemKindType::SKELETON:
77     case ItemKindType::SPIKE:
78     case ItemKindType::WHISTLE:
79         return true;
80     case ItemKindType::FOOD:
81     case ItemKindType::POTION:
82     case ItemKindType::SCROLL:
83     case ItemKindType::ROD:
84         return true;
85
86     default:
87         break;
88     }
89
90     return false;
91 }
92
93 /*!
94  * @brief 各種語彙からランダムな名前を作成する / Create a name from random parts.
95  * @param out_string 作成した名を保管する参照ポインタ
96  * @details 日本語の場合 aname_j.txt 英語の場合確率に応じて
97  * syllables 配列と elvish.txt を組み合わせる。\n
98  */
99 void get_table_name_aux(char *out_string)
100 {
101 #ifdef JP
102     char syllable[80];
103     get_rnd_line("aname_j.txt", 1, syllable);
104     strcpy(out_string, syllable);
105     get_rnd_line("aname_j.txt", 2, syllable);
106     strcat(out_string, syllable);
107 #else
108 #define MAX_SYLLABLES 164 /* Used with scrolls (see below) */
109
110     static concptr syllables[MAX_SYLLABLES] = { "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze", "ash", "aus", "ban", "bar", "bat", "bek",
111         "bie", "bin", "bit", "bjor", "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf", "dan", "den", "der", "doe", "dok", "eep", "el", "eng",
112         "er", "ere", "erk", "esh", "evs", "fa", "fid", "flit", "for", "fri", "fu", "gan", "gar", "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion",
113         "ip", "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nag", "nej",
114         "nelg", "nep", "ner", "nes", "nis", "nih", "nin", "o", "od", "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po", "pot", "prok", "re",
115         "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna", "sne", "snik", "sno", "so", "sol", "sri",
116         "sta", "sun", "ta", "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u", "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
117         "wed", "werg", "wex", "whon", "wun", "x", "yerg", "yp", "zun", "tri", "blaa", "jah", "bul", "on", "foo", "ju", "xuxu" };
118
119     int testcounter = randint1(3) + 1;
120     strcpy(out_string, "");
121     if (randint1(3) == 2) {
122         while (testcounter--) {
123             strcat(out_string, syllables[randint0(MAX_SYLLABLES)]);
124         }
125     } else {
126         char syllable[80];
127         testcounter = randint1(2) + 1;
128         while (testcounter--) {
129             (void)get_rnd_line("elvish.txt", 0, syllable);
130             strcat(out_string, syllable);
131         }
132     }
133
134     out_string[0] = toupper(out_string[1]);
135     out_string[16] = '\0';
136 #endif
137 }
138
139 /*!
140  * @brief ランダムな名前をアーティファクト銘として整形する。 / Create a name from random parts with quotes.
141  * @param out_string 作成した名を保管する参照ポインタ
142  * @details get_table_name_aux()ほぼ完全に実装を依存している。
143  */
144 void get_table_name(char *out_string)
145 {
146     char buff[80];
147     get_table_name_aux(buff);
148     sprintf(out_string, _("『%s』", "'%s'"), buff);
149 }
150
151 /*!
152  * @brief ランダムなシンダリン銘を作成する / Make random Sindarin name
153  * @param out_string 作成した名を保管する参照ポインタ
154  * @details sname.txtが語幹の辞書となっている。
155  */
156 void get_table_sindarin_aux(char *out_string)
157 {
158     char syllable[80];
159 #ifdef JP
160     char tmp[80];
161 #endif
162
163     get_rnd_line("sname.txt", 1, syllable);
164     strcpy(_(tmp, out_string), syllable);
165     get_rnd_line("sname.txt", 2, syllable);
166 #ifdef JP
167     strcat(tmp, syllable);
168     sindarin_to_kana(out_string, tmp);
169 #else
170     strcat(out_string, syllable);
171 #endif
172 }
173
174 /*!
175  * @brief シンダリン銘をアーティファクト用に整形する。 / Make random Sindarin name with quotes
176  * @param out_string 作成した名を保管する参照ポインタ
177  * @details get_table_sindarin_aux()ほぼ完全に実装を依存している。
178  */
179 void get_table_sindarin(char *out_string)
180 {
181     char buff[80];
182     get_table_sindarin_aux(buff);
183     sprintf(out_string, _("『%s』", "'%s'"), buff);
184 }
185
186 /*!
187  * @brief ベースアイテムの未確定名を共通tval間でシャッフルする / Shuffle flavor indices of a group of objects with given tval
188  * @param tval シャッフルしたいtval
189  * @details 巻物、各種魔道具などに利用される。
190  */
191 static void shuffle_flavors(ItemKindType tval)
192 {
193     std::vector<std::reference_wrapper<IDX>> flavor_idx_ref_list;
194     for (const auto &k_ref : k_info) {
195         if (k_ref.tval != tval) {
196             continue;
197         }
198
199         if (!k_ref.flavor) {
200             continue;
201         }
202
203         if (k_ref.flags.has(TR_FIXED_FLAVOR)) {
204             continue;
205         }
206
207         flavor_idx_ref_list.push_back(k_info[k_ref.idx].flavor);
208     }
209
210     rand_shuffle(flavor_idx_ref_list.begin(), flavor_idx_ref_list.end());
211 }
212
213 /*!
214  * @brief ゲーム開始時に行われるベースアイテムの初期化ルーチン / Prepare the "variable" part of the "k_info" array.
215  * @param なし
216  */
217 void flavor_init(void)
218 {
219     const auto state_backup = w_ptr->rng.get_state();
220     w_ptr->rng.set_state(w_ptr->seed_flavor);
221     for (auto &k_ref : k_info) {
222         if (k_ref.flavor_name.empty()) {
223             continue;
224         }
225
226         k_ref.flavor = k_ref.idx;
227     }
228
229     shuffle_flavors(ItemKindType::RING);
230     shuffle_flavors(ItemKindType::AMULET);
231     shuffle_flavors(ItemKindType::STAFF);
232     shuffle_flavors(ItemKindType::WAND);
233     shuffle_flavors(ItemKindType::ROD);
234     shuffle_flavors(ItemKindType::FOOD);
235     shuffle_flavors(ItemKindType::POTION);
236     shuffle_flavors(ItemKindType::SCROLL);
237     w_ptr->rng.set_state(state_backup);
238     for (auto &k_ref : k_info) {
239         if (k_ref.idx == 0 || k_ref.name.empty()) {
240             continue;
241         }
242
243         if (!k_ref.flavor) {
244             k_ref.aware = true;
245         }
246
247         k_ref.easy_know = object_easy_know(k_ref.idx);
248     }
249 }
250
251 /*!
252  * @brief nameバッファ内からベースアイテム名を返す / Strip an "object name" into a buffer
253  * @param buf ベースアイテム格納先の参照ポインタ
254  * @param k_idx ベースアイテムID
255  */
256 std::string strip_name(KIND_OBJECT_IDX k_idx)
257 {
258     auto k_ptr = &k_info[k_idx];
259     auto tok = str_split(k_ptr->name, ' ');
260     std::stringstream name;
261     for (const auto &s : tok) {
262         if (s == "" || s == "~" || s == "&" || s == "#") {
263             continue;
264         }
265
266         auto offset = 0;
267         auto endpos = s.size();
268         auto is_kanji = false;
269
270         if (s[0] == '~' || s[0] == '#') {
271             offset++;
272         }
273 #ifdef JP
274         if (s.size() > 2) {
275             is_kanji = iskanji(s[endpos - 2]);
276         }
277
278 #endif
279         if (!is_kanji && (s[endpos - 1] == '~' || s[endpos - 1] == '#')) {
280             endpos--;
281         }
282
283         name << s.substr(offset, endpos);
284     }
285
286     name << " ";
287     return name.str();
288 }