OSDN Git Service

Merge pull request #1535 from Hourier/feature/Simplify-Current-World-Pointer
[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 "mind/mind-sniper.h"
22 #include "mind/mind-weaponsmith.h"
23 #include "monster-race/monster-race.h"
24 #include "monster-race/race-flags1.h"
25 #include "object-enchant/object-ego.h"
26 #include "object-enchant/special-object-flags.h"
27 #include "object-enchant/tr-types.h"
28 #include "object-enchant/trg-types.h"
29 #include "object-hook/hook-quest.h"
30 #include "object/object-flags.h"
31 #include "object/object-info.h"
32 #include "object/object-kind.h"
33 #include "perception/object-perception.h"
34 #include "player-info/class-info.h"
35 #include "player/player-status.h"
36 #include "sv-definition/sv-food-types.h"
37 #include "sv-definition/sv-lite-types.h"
38 #include "util/bit-flags-calculator.h"
39 #include "util/quarks.h"
40 #include "util/string-processor.h"
41 #include "world/world.h"
42 #ifdef JP
43 #include "locale/japanese.h"
44 #else
45 #include "locale/english.h"
46 #endif
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     object_kind *k_ptr = &k_info[i];
58     switch (k_ptr->tval) {
59     case TV_LIFE_BOOK:
60     case TV_SORCERY_BOOK:
61     case TV_NATURE_BOOK:
62     case TV_CHAOS_BOOK:
63     case TV_DEATH_BOOK:
64     case TV_TRUMP_BOOK:
65     case TV_ARCANE_BOOK:
66     case TV_CRAFT_BOOK:
67     case TV_DEMON_BOOK:
68     case TV_CRUSADE_BOOK:
69     case TV_MUSIC_BOOK:
70     case TV_HISSATSU_BOOK:
71     case TV_HEX_BOOK:
72         return true;
73     case TV_FLASK:
74     case TV_JUNK:
75     case TV_BOTTLE:
76     case TV_SKELETON:
77     case TV_SPIKE:
78     case TV_WHISTLE:
79         return true;
80     case TV_FOOD:
81     case TV_POTION:
82     case TV_SCROLL:
83     case TV_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     } 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(tval_type tval)
191 {
192     KIND_OBJECT_IDX *k_idx_list;
193     KIND_OBJECT_IDX k_idx_list_num = 0;
194     C_MAKE(k_idx_list, max_k_idx, KIND_OBJECT_IDX);
195     for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++) {
196         object_kind *k_ptr = &k_info[i];
197         if (k_ptr->tval != tval)
198             continue;
199
200         if (!k_ptr->flavor)
201             continue;
202
203         if (k_ptr->flags.has(TR_FIXED_FLAVOR))
204             continue;
205
206         k_idx_list[k_idx_list_num] = i;
207         k_idx_list_num++;
208     }
209
210     for (KIND_OBJECT_IDX i = 0; i < k_idx_list_num; i++) {
211         object_kind *k1_ptr = &k_info[k_idx_list[i]];
212         object_kind *k2_ptr = &k_info[k_idx_list[randint0(k_idx_list_num)]];
213         int16_t tmp = k1_ptr->flavor;
214         k1_ptr->flavor = k2_ptr->flavor;
215         k2_ptr->flavor = tmp;
216     }
217
218     C_KILL(k_idx_list, max_k_idx, int16_t);
219 }
220
221 /*!
222  * @brief ゲーム開始時に行われるベースアイテムの初期化ルーチン / Prepare the "variable" part of the "k_info" array.
223  * @param なし
224  */
225 void flavor_init(void)
226 {
227     uint32_t state_backup[4];
228     Rand_state_backup(state_backup);
229     Rand_state_set(w_ptr->seed_flavor);
230     for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++) {
231         object_kind *k_ptr = &k_info[i];
232         if (k_ptr->flavor_name.empty())
233             continue;
234
235         k_ptr->flavor = i;
236     }
237
238     shuffle_flavors(TV_RING);
239     shuffle_flavors(TV_AMULET);
240     shuffle_flavors(TV_STAFF);
241     shuffle_flavors(TV_WAND);
242     shuffle_flavors(TV_ROD);
243     shuffle_flavors(TV_FOOD);
244     shuffle_flavors(TV_POTION);
245     shuffle_flavors(TV_SCROLL);
246     Rand_state_restore(state_backup);
247     for (KIND_OBJECT_IDX i = 1; i < max_k_idx; i++) {
248         object_kind *k_ptr = &k_info[i];
249         if (k_ptr->name.empty())
250             continue;
251
252         if (!k_ptr->flavor)
253             k_ptr->aware = true;
254
255         k_ptr->easy_know = object_easy_know(i);
256     }
257 }
258
259 /*!
260  * @brief nameバッファ内からベースアイテム名を返す / Strip an "object name" into a buffer
261  * @param buf ベースアイテム格納先の参照ポインタ
262  * @param k_idx ベースアイテムID
263  */
264 void strip_name(char *buf, KIND_OBJECT_IDX k_idx)
265 {
266     auto k_ptr = &k_info[k_idx];
267     auto tok = str_split(k_ptr->name, ' ');
268     std::string name = "";
269     for (auto s : tok) {
270         if (s == "" || s == "~" || s == "&" || s == "#")
271             continue;
272
273         auto offset = 0;
274         auto endpos = s.size();
275         auto is_kanji = false;
276
277         if (s[0] == '~' || s[0] == '#')
278             offset++;
279 #ifdef JP
280         if (s.size() > 2)
281             is_kanji = iskanji(s[endpos - 2]);
282
283 #endif
284         if (!is_kanji && (s[endpos - 1] == '~' || s[endpos - 1] == '#'))
285             endpos--;
286
287         name += s.substr(offset, endpos);
288     }
289
290     name += " ";
291     strcpy(buf, name.c_str());
292 }