OSDN Git Service

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