OSDN Git Service

Merge pull request #1471 from sikabane-works/release/3.0.0Alpha37
[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-quest.h"
31 #include "object/object-flags.h"
32 #include "object/object-info.h"
33 #include "object/object-kind.h"
34 #include "perception/object-perception.h"
35 #include "player/player-class.h"
36 #include "player/player-status.h"
37 #include "sv-definition/sv-food-types.h"
38 #include "sv-definition/sv-lite-types.h"
39 #include "util/bit-flags-calculator.h"
40 #include "util/quarks.h"
41 #include "util/string-processor.h"
42 #include "world/world.h"
43 #ifdef JP
44 #include "locale/japanese.h"
45 #else
46 #include "locale/english.h"
47 #endif
48
49 /*!
50  * @brief 最初から簡易な名称が明らかになるベースアイテムの判定。 /  Certain items, if aware, are known instantly
51  * @param i ベースアイテムID
52  * @return 簡易名称を明らかにするならTRUEを返す。
53  * @details
54  * This function is used only by "flavor_init()"
55  */
56 static bool object_easy_know(int i)
57 {
58     object_kind *k_ptr = &k_info[i];
59     switch (k_ptr->tval) {
60     case TV_LIFE_BOOK:
61     case TV_SORCERY_BOOK:
62     case TV_NATURE_BOOK:
63     case TV_CHAOS_BOOK:
64     case TV_DEATH_BOOK:
65     case TV_TRUMP_BOOK:
66     case TV_ARCANE_BOOK:
67     case TV_CRAFT_BOOK:
68     case TV_DEMON_BOOK:
69     case TV_CRUSADE_BOOK:
70     case TV_MUSIC_BOOK:
71     case TV_HISSATSU_BOOK:
72     case TV_HEX_BOOK:
73         return true;
74     case TV_FLASK:
75     case TV_JUNK:
76     case TV_BOTTLE:
77     case TV_SKELETON:
78     case TV_SPIKE:
79     case TV_WHISTLE:
80         return true;
81     case TV_FOOD:
82     case TV_POTION:
83     case TV_SCROLL:
84     case TV_ROD:
85         return true;
86
87     default:
88         break;
89     }
90
91     return false;
92 }
93
94 /*!
95  * @brief 各種語彙からランダムな名前を作成する / Create a name from random parts.
96  * @param out_string 作成した名を保管する参照ポインタ
97  * @details 日本語の場合 aname_j.txt 英語の場合確率に応じて
98  * syllables 配列と elvish.txt を組み合わせる。\n
99  */
100 void get_table_name_aux(char *out_string)
101 {
102 #ifdef JP
103     char syllable[80];
104     get_rnd_line("aname_j.txt", 1, syllable);
105     strcpy(out_string, syllable);
106     get_rnd_line("aname_j.txt", 2, syllable);
107     strcat(out_string, syllable);
108 #else
109 #define MAX_SYLLABLES 164 /* Used with scrolls (see below) */
110
111     static concptr syllables[MAX_SYLLABLES] = { "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze", "ash", "aus", "ban", "bar", "bat", "bek",
112         "bie", "bin", "bit", "bjor", "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf", "dan", "den", "der", "doe", "dok", "eep", "el", "eng",
113         "er", "ere", "erk", "esh", "evs", "fa", "fid", "flit", "for", "fri", "fu", "gan", "gar", "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion",
114         "ip", "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech", "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nag", "nej",
115         "nelg", "nep", "ner", "nes", "nis", "nih", "nin", "o", "od", "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po", "pot", "prok", "re",
116         "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna", "sne", "snik", "sno", "so", "sol", "sri",
117         "sta", "sun", "ta", "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u", "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
118         "wed", "werg", "wex", "whon", "wun", "x", "yerg", "yp", "zun", "tri", "blaa", "jah", "bul", "on", "foo", "ju", "xuxu" };
119
120     int testcounter = randint1(3) + 1;
121     strcpy(out_string, "");
122     if (randint1(3) == 2) {
123         while (testcounter--)
124             strcat(out_string, syllables[randint0(MAX_SYLLABLES)]);
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(tval_type tval)
192 {
193     KIND_OBJECT_IDX *k_idx_list;
194     KIND_OBJECT_IDX k_idx_list_num = 0;
195     C_MAKE(k_idx_list, max_k_idx, KIND_OBJECT_IDX);
196     for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++) {
197         object_kind *k_ptr = &k_info[i];
198         if (k_ptr->tval != tval)
199             continue;
200
201         if (!k_ptr->flavor)
202             continue;
203
204         if (has_flag(k_ptr->flags, TR_FIXED_FLAVOR))
205             continue;
206
207         k_idx_list[k_idx_list_num] = i;
208         k_idx_list_num++;
209     }
210
211     for (KIND_OBJECT_IDX i = 0; i < k_idx_list_num; i++) {
212         object_kind *k1_ptr = &k_info[k_idx_list[i]];
213         object_kind *k2_ptr = &k_info[k_idx_list[randint0(k_idx_list_num)]];
214         int16_t tmp = k1_ptr->flavor;
215         k1_ptr->flavor = k2_ptr->flavor;
216         k2_ptr->flavor = tmp;
217     }
218
219     C_KILL(k_idx_list, max_k_idx, int16_t);
220 }
221
222 /*!
223  * @brief ゲーム開始時に行われるベースアイテムの初期化ルーチン / Prepare the "variable" part of the "k_info" array.
224  * @param なし
225  */
226 void flavor_init(void)
227 {
228     uint32_t state_backup[4];
229     Rand_state_backup(state_backup);
230     Rand_state_set(current_world_ptr->seed_flavor);
231     for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++) {
232         object_kind *k_ptr = &k_info[i];
233         if (k_ptr->flavor_name.empty())
234             continue;
235
236         k_ptr->flavor = i;
237     }
238
239     shuffle_flavors(TV_RING);
240     shuffle_flavors(TV_AMULET);
241     shuffle_flavors(TV_STAFF);
242     shuffle_flavors(TV_WAND);
243     shuffle_flavors(TV_ROD);
244     shuffle_flavors(TV_FOOD);
245     shuffle_flavors(TV_POTION);
246     shuffle_flavors(TV_SCROLL);
247     Rand_state_restore(state_backup);
248     for (KIND_OBJECT_IDX i = 1; i < max_k_idx; i++) {
249         object_kind *k_ptr = &k_info[i];
250         if (k_ptr->name.empty())
251             continue;
252
253         if (!k_ptr->flavor)
254             k_ptr->aware = true;
255
256         k_ptr->easy_know = object_easy_know(i);
257     }
258 }
259
260 /*!
261  * @brief nameバッファ内からベースアイテム名を返す / Strip an "object name" into a buffer
262  * @param buf ベースアイテム格納先の参照ポインタ
263  * @param k_idx ベースアイテムID
264  */
265 void strip_name(char *buf, KIND_OBJECT_IDX k_idx)
266 {
267     auto k_ptr = &k_info[k_idx];
268     auto tok = str_split(k_ptr->name, ' ');
269     std::string name = "";
270     for (auto s : tok) {
271         if (s == "" || s == "~" || s == "&" || s == "#")
272             continue;
273
274         auto offset = 0;
275         auto endpos = s.size();
276         auto is_kanji = false;
277
278         if (s[0] == '~' || s[0] == '#')
279             offset++;
280 #ifdef JP
281         if (s.size() > 2)
282             is_kanji = iskanji(s[endpos - 2]);
283
284 #endif
285         if (!is_kanji && (s[endpos - 1] == '~' || s[endpos - 1] == '#'))
286             endpos--;
287
288         name += s.substr(offset, endpos);
289     }
290
291     name += " ";
292     strcpy(buf, name.c_str());
293 }