OSDN Git Service

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