OSDN Git Service

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