OSDN Git Service

Merge remote-tracking branch 'remotes/hengbandosx/english-lore-edits' into feature...
[hengband/hengband.git] / src / artifact / random-art-generator.c
1 /*!
2  * @brief ランダムアーティファクトの生成 / Artifact code
3  * @date 2020/07/14
4  * @author Hourier
5  */
6
7 #include "artifact/random-art-generator.h"
8 #include "artifact/random-art-activation.h"
9 #include "artifact/random-art-bias-types.h"
10 #include "artifact/random-art-characteristics.h"
11 #include "artifact/random-art-misc.h"
12 #include "artifact/random-art-pval-investor.h"
13 #include "artifact/random-art-resistance.h"
14 #include "artifact/random-art-slay.h"
15 #include "core/asking-player.h"
16 #include "core/window-redrawer.h"
17 #include "flavor/object-flavor.h"
18 #include "game-option/cheat-types.h"
19 #include "object-enchant/special-object-flags.h"
20 #include "object-enchant/tr-types.h"
21 #include "object-hook/hook-armor.h"
22 #include "object-hook/hook-checker.h"
23 #include "object-hook/hook-weapon.h"
24 #include "object/object-flags.h"
25 #include "object/object-kind-hook.h"
26 #include "object/object-kind.h"
27 #include "object/object-value-calc.h"
28 #include "perception/identification.h"
29 #include "perception/object-perception.h"
30 #include "player-info/avatar.h"
31 #include "sv-definition/sv-weapon-types.h"
32 #include "util/bit-flags-calculator.h"
33 #include "util/quarks.h"
34 #include "view/display-messages.h"
35 #include "wizard/artifact-bias-table.h"
36 #include "wizard/wizard-messages.h"
37 #include "world/world.h"
38
39 static bool weakening_artifact(player_type *player_ptr, object_type *o_ptr)
40 {
41     KIND_OBJECT_IDX k_idx = lookup_kind(o_ptr->tval, o_ptr->sval);
42     object_kind *k_ptr = &k_info[k_idx];
43     BIT_FLAGS flgs[TR_FLAG_SIZE];
44     object_flags(player_ptr, o_ptr, flgs);
45
46     if (has_flag(flgs, TR_KILL_EVIL)) {
47         remove_flag(o_ptr->art_flags, TR_KILL_EVIL);
48         add_flag(o_ptr->art_flags, TR_SLAY_EVIL);
49         return TRUE;
50     }
51
52     if (k_ptr->dd < o_ptr->dd) {
53         o_ptr->dd--;
54         return TRUE;
55     }
56
57     if (k_ptr->ds < o_ptr->ds) {
58         o_ptr->ds--;
59         return TRUE;
60     }
61
62     if (o_ptr->to_d > 10) {
63         o_ptr->to_d = o_ptr->to_d - damroll(1, 6);
64         if (o_ptr->to_d < 10) {
65             o_ptr->to_d = 10;
66         }
67
68         return TRUE;
69     }
70
71     return FALSE;
72 }
73
74 static void set_artifact_bias(player_type *player_ptr, object_type *o_ptr, int *warrior_artifact_bias)
75 {
76     switch (player_ptr->pclass) {
77     case CLASS_WARRIOR:
78     case CLASS_BERSERKER:
79     case CLASS_ARCHER:
80     case CLASS_SAMURAI:
81     case CLASS_CAVALRY:
82     case CLASS_SMITH:
83         o_ptr->artifact_bias = BIAS_WARRIOR;
84         break;
85     case CLASS_MAGE:
86     case CLASS_HIGH_MAGE:
87     case CLASS_SORCERER:
88     case CLASS_MAGIC_EATER:
89     case CLASS_BLUE_MAGE:
90         o_ptr->artifact_bias = BIAS_MAGE;
91         break;
92     case CLASS_PRIEST:
93         o_ptr->artifact_bias = BIAS_PRIESTLY;
94         break;
95     case CLASS_ROGUE:
96     case CLASS_NINJA:
97         o_ptr->artifact_bias = BIAS_ROGUE;
98         *warrior_artifact_bias = 25;
99         break;
100     case CLASS_RANGER:
101     case CLASS_SNIPER:
102         o_ptr->artifact_bias = BIAS_RANGER;
103         *warrior_artifact_bias = 30;
104         break;
105     case CLASS_PALADIN:
106         o_ptr->artifact_bias = BIAS_PRIESTLY;
107         *warrior_artifact_bias = 40;
108         break;
109     case CLASS_WARRIOR_MAGE:
110     case CLASS_RED_MAGE:
111         o_ptr->artifact_bias = BIAS_MAGE;
112         *warrior_artifact_bias = 40;
113         break;
114     case CLASS_CHAOS_WARRIOR:
115         o_ptr->artifact_bias = BIAS_CHAOS;
116         *warrior_artifact_bias = 40;
117         break;
118     case CLASS_MONK:
119     case CLASS_FORCETRAINER:
120         o_ptr->artifact_bias = BIAS_PRIESTLY;
121         break;
122     case CLASS_MINDCRAFTER:
123     case CLASS_BARD:
124         if (randint1(5) > 2)
125             o_ptr->artifact_bias = BIAS_PRIESTLY;
126         break;
127     case CLASS_TOURIST:
128         if (randint1(5) > 2)
129             o_ptr->artifact_bias = BIAS_WARRIOR;
130         break;
131     case CLASS_IMITATOR:
132         if (randint1(2) > 1)
133             o_ptr->artifact_bias = BIAS_RANGER;
134         break;
135     case CLASS_BEASTMASTER:
136         o_ptr->artifact_bias = BIAS_CHR;
137         *warrior_artifact_bias = 50;
138         break;
139     case CLASS_MIRROR_MASTER:
140         if (randint1(4) > 1)
141             o_ptr->artifact_bias = BIAS_MAGE;
142         else
143             o_ptr->artifact_bias = BIAS_ROGUE;
144         
145         break;
146     }
147 }
148
149 static void decide_warrior_bias(player_type *player_ptr, object_type *o_ptr, const bool a_scroll)
150 {
151     int warrior_artifact_bias = 0;
152     if (a_scroll && one_in_(4))
153         set_artifact_bias(player_ptr, o_ptr, &warrior_artifact_bias);
154
155     if (a_scroll && (randint1(100) <= warrior_artifact_bias))
156         o_ptr->artifact_bias = BIAS_WARRIOR;
157 }
158
159 static bool decide_random_art_cursed(const bool a_scroll, object_type *o_ptr)
160 {
161     if (!a_scroll && one_in_(A_CURSED))
162         return TRUE;
163
164     if (((o_ptr->tval == TV_AMULET) || (o_ptr->tval == TV_RING)) && object_is_cursed(o_ptr))
165         return TRUE;
166
167     return FALSE;
168 }
169
170 static int decide_random_art_power(const bool a_cursed)
171 {
172     int powers = randint1(5) + 1;
173     while (one_in_(powers) || one_in_(7) || one_in_(10))
174         powers++;
175
176     if (!a_cursed && one_in_(WEIRD_LUCK))
177         powers *= 2;
178
179     if (a_cursed)
180         powers /= 2;
181
182     return powers;
183 }
184
185 static void invest_powers(player_type *player_ptr, object_type *o_ptr, int *powers, bool *has_pval, const bool a_cursed)
186 {
187     int max_type = object_is_weapon_ammo(o_ptr) ? 7 : 5;
188     while ((*powers)--) {
189         switch (randint1(max_type)) {
190         case 1:
191         case 2:
192             random_plus(o_ptr);
193             *has_pval = TRUE;
194             break;
195         case 3:
196         case 4:
197             if (one_in_(2) && object_is_weapon_ammo(o_ptr) && (o_ptr->tval != TV_BOW)) {
198                 if (a_cursed && !one_in_(13))
199                     break;
200                 if (one_in_(13)) {
201                     if (one_in_(o_ptr->ds + 4))
202                         o_ptr->ds++;
203                 } else {
204                     if (one_in_(o_ptr->dd + 1))
205                         o_ptr->dd++;
206                 }
207             } else
208                 random_resistance(o_ptr);
209
210             break;
211         case 5:
212             random_misc(player_ptr, o_ptr);
213             break;
214         case 6:
215         case 7:
216             random_slay(o_ptr);
217             break;
218         default:
219             if (current_world_ptr->wizard)
220                 msg_print("Switch error in become_random_artifact!");
221
222             (*powers)++;
223         }
224     };
225 }
226
227 static void strengthen_pval(object_type *o_ptr)
228 {
229     if (has_flag(o_ptr->art_flags, TR_BLOWS)) {
230         o_ptr->pval = randint1(2);
231         if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
232             o_ptr->pval++;
233     } else {
234         do {
235             o_ptr->pval++;
236         } while (o_ptr->pval < randint1(5) || one_in_(o_ptr->pval));
237     }
238
239     if ((o_ptr->pval > 4) && !one_in_(WEIRD_LUCK))
240         o_ptr->pval = 4;
241 }
242
243 /*!
244  * @brief 防具ならばAC修正、武具なら殺戮修正を付与する
245  * @param player_ptr プレーヤーへの参照ポインタ
246  * @param o_ptr ランダムアーティファクトを示すアイテムへの参照ポインタ
247  * @return なし
248  */
249 static void invest_positive_modified_value(player_type *player_ptr, object_type *o_ptr)
250 {
251     if (object_is_armour(player_ptr, o_ptr)) {
252         o_ptr->to_a += randint1(o_ptr->to_a > 19 ? 1 : 20 - o_ptr->to_a);
253         return;
254     }
255     
256     if (!object_is_weapon_ammo(o_ptr))
257         return;
258
259     o_ptr->to_h += randint1(o_ptr->to_h > 19 ? 1 : 20 - o_ptr->to_h);
260     o_ptr->to_d += randint1(o_ptr->to_d > 19 ? 1 : 20 - o_ptr->to_d);
261     if ((has_flag(o_ptr->art_flags, TR_WIS)) && (o_ptr->pval > 0))
262         add_flag(o_ptr->art_flags, TR_BLESSED);
263 }
264
265 /*!
266  * @brief 防具のAC修正が高すぎた場合に弱化させる
267  * @param player_ptr プレーヤーへの参照ポインタ
268  * @param o_ptr ランダムアーティファクトを示すアイテムへの参照ポインタ
269  * @return なし
270  */
271 static void invest_negative_modified_value(player_type *player_ptr, object_type *o_ptr)
272 {
273     if (!object_is_armour(player_ptr, o_ptr))
274         return;
275
276     while ((o_ptr->to_d + o_ptr->to_h) > 20) {
277         if (one_in_(o_ptr->to_d) && one_in_(o_ptr->to_h))
278             break;
279
280         o_ptr->to_d -= (HIT_POINT)randint0(3);
281         o_ptr->to_h -= (HIT_PROB)randint0(3);
282     }
283
284     while ((o_ptr->to_d + o_ptr->to_h) > 10) {
285         if (one_in_(o_ptr->to_d) || one_in_(o_ptr->to_h))
286             break;
287
288         o_ptr->to_d -= (HIT_POINT)randint0(3);
289         o_ptr->to_h -= (HIT_PROB)randint0(3);
290     }
291 }
292
293 static void reset_flags_poison_needle(object_type *o_ptr)
294 {
295     if ((o_ptr->tval != TV_SWORD) || (o_ptr->sval != SV_POISON_NEEDLE))
296         return;
297
298     o_ptr->to_h = 0;
299     o_ptr->to_d = 0;
300     remove_flag(o_ptr->art_flags, TR_BLOWS);
301     remove_flag(o_ptr->art_flags, TR_FORCE_WEAPON);
302     remove_flag(o_ptr->art_flags, TR_SLAY_ANIMAL);
303     remove_flag(o_ptr->art_flags, TR_SLAY_EVIL);
304     remove_flag(o_ptr->art_flags, TR_SLAY_UNDEAD);
305     remove_flag(o_ptr->art_flags, TR_SLAY_DEMON);
306     remove_flag(o_ptr->art_flags, TR_SLAY_ORC);
307     remove_flag(o_ptr->art_flags, TR_SLAY_TROLL);
308     remove_flag(o_ptr->art_flags, TR_SLAY_GIANT);
309     remove_flag(o_ptr->art_flags, TR_SLAY_DRAGON);
310     remove_flag(o_ptr->art_flags, TR_KILL_DRAGON);
311     remove_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
312     remove_flag(o_ptr->art_flags, TR_VORPAL);
313     remove_flag(o_ptr->art_flags, TR_BRAND_POIS);
314     remove_flag(o_ptr->art_flags, TR_BRAND_ACID);
315     remove_flag(o_ptr->art_flags, TR_BRAND_ELEC);
316     remove_flag(o_ptr->art_flags, TR_BRAND_FIRE);
317     remove_flag(o_ptr->art_flags, TR_BRAND_COLD);
318 }
319
320 static int decide_random_art_power_level(object_type *o_ptr, const bool a_cursed, const int total_flags)
321 {
322     if (object_is_weapon_ammo(o_ptr)) {
323         if (a_cursed)
324             return 0;
325
326         if (total_flags < 20000)
327             return 1;
328
329         if (total_flags < 45000)
330             return 2;
331
332         return 3;
333     }
334
335     if (a_cursed)
336         return 0;
337
338     if (total_flags < 15000)
339         return 1;
340
341     if (total_flags < 35000)
342         return 2;
343
344     return 3;
345 }
346
347 static void name_unnatural_random_artifact(player_type *player_ptr, object_type *o_ptr, const bool a_scroll, const int power_level, GAME_TEXT *new_name)
348 {
349     if (!a_scroll) {
350         get_random_name(o_ptr, new_name, object_is_armour(player_ptr, o_ptr), power_level);
351         return;
352     }
353
354     GAME_TEXT dummy_name[MAX_NLEN] = "";
355     concptr ask_msg = _("このアーティファクトを何と名付けますか?", "What do you want to call the artifact? ");
356     object_aware(player_ptr, o_ptr);
357     object_known(o_ptr);
358     o_ptr->ident |= IDENT_FULL_KNOWN;
359     o_ptr->art_name = quark_add("");
360     (void)screen_object(player_ptr, o_ptr, 0L);
361     if (!get_string(ask_msg, dummy_name, sizeof dummy_name) || !dummy_name[0]) {
362         if (one_in_(2)) {
363             get_table_sindarin_aux(dummy_name);
364         } else {
365             get_table_name_aux(dummy_name);
366         }
367     }
368
369     sprintf(new_name, _("《%s》", "'%s'"), dummy_name);
370     chg_virtue(player_ptr, V_INDIVIDUALISM, 2);
371     chg_virtue(player_ptr, V_ENCHANT, 5);
372 }
373
374 static void generate_unnatural_random_artifact(player_type *player_ptr, object_type *o_ptr, const bool a_scroll, const int power_level, const int max_powers, const int total_flags)
375 {
376     GAME_TEXT new_name[1024];
377     strcpy(new_name, "");
378     name_unnatural_random_artifact(player_ptr, o_ptr, a_scroll, power_level, new_name);
379     o_ptr->art_name = quark_add(new_name);
380     msg_format_wizard(player_ptr, CHEAT_OBJECT,
381         _("パワー %d で 価値%ld のランダムアーティファクト生成 バイアスは「%s」", "Random artifact generated - Power:%d Value:%d Bias:%s."), max_powers,
382         total_flags, artifact_bias_name[o_ptr->artifact_bias]);
383     player_ptr->window |= PW_INVEN | PW_EQUIP;
384 }
385
386 /*!
387  * @brief ランダムアーティファクト生成のメインルーチン
388  * @details 既に生成が済んでいるオブジェクトの構造体を、アーティファクトとして強化する。
389  * @param player_ptr プレーヤーへの参照ポインタ
390  * @param o_ptr 対象のオブジェクト構造体ポインタ
391  * @param a_scroll アーティファクト生成の巻物上の処理。呪いのアーティファクトが生成対象外となる。
392  * @return 常にTRUE(1)を返す
393  */
394 bool become_random_artifact(player_type *player_ptr, object_type *o_ptr, bool a_scroll)
395 {
396     o_ptr->artifact_bias = 0;
397     o_ptr->name1 = 0;
398     o_ptr->name2 = 0;
399     for (int i = 0; i < TR_FLAG_SIZE; i++)
400         o_ptr->art_flags[i] |= k_info[o_ptr->k_idx].flags[i];
401
402     bool has_pval = o_ptr->pval != 0;
403     decide_warrior_bias(player_ptr, o_ptr, a_scroll);
404
405     bool a_cursed = decide_random_art_cursed(a_scroll, o_ptr);
406     int powers = decide_random_art_power(a_cursed);
407     int max_powers = powers;
408     invest_powers(player_ptr, o_ptr, &powers, &has_pval, a_cursed);
409     if (has_pval)
410         strengthen_pval(o_ptr);
411
412     invest_positive_modified_value(player_ptr, o_ptr);
413     add_flag(o_ptr->art_flags, TR_IGNORE_ACID);
414     add_flag(o_ptr->art_flags, TR_IGNORE_ELEC);
415     add_flag(o_ptr->art_flags, TR_IGNORE_FIRE);
416     add_flag(o_ptr->art_flags, TR_IGNORE_COLD);
417
418     s32b total_flags = flag_cost(player_ptr, o_ptr, o_ptr->pval);
419     if (a_cursed)
420         curse_artifact(player_ptr, o_ptr);
421
422     if (!a_cursed && one_in_(object_is_armour(player_ptr, o_ptr) ? ACTIVATION_CHANCE * 2 : ACTIVATION_CHANCE)) {
423         o_ptr->xtra2 = 0;
424         give_activation_power(o_ptr);
425     }
426
427     invest_negative_modified_value(player_ptr, o_ptr);
428     if (((o_ptr->artifact_bias == BIAS_MAGE) || (o_ptr->artifact_bias == BIAS_INT)) && (o_ptr->tval == TV_GLOVES))
429         add_flag(o_ptr->art_flags, TR_FREE_ACT);
430
431     reset_flags_poison_needle(o_ptr);
432     int power_level = decide_random_art_power_level(o_ptr, a_cursed, total_flags);
433     while (has_extreme_damage_rate(player_ptr, o_ptr) && !one_in_(SWORDFISH_LUCK))
434         weakening_artifact(player_ptr, o_ptr);
435
436     generate_unnatural_random_artifact(player_ptr, o_ptr, a_scroll, power_level, max_powers, total_flags);
437     return TRUE;
438 }