OSDN Git Service

[Refactor] #40561 Separated invest_activation_ranger() from give_activation_power()
[hengbandforosx/hengbandosx.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/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 (have_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 /*!
75  * @brief ランダムアーティファクト生成のメインルーチン
76  * @details 既に生成が済んでいるオブジェクトの構造体を、アーティファクトとして強化する。
77  * @param player_ptr プレーヤーへの参照ポインタ
78  * @param o_ptr 対象のオブジェクト構造体ポインタ
79  * @param a_scroll アーティファクト生成の巻物上の処理。呪いのアーティファクトが生成対象外となる。
80  * @return 常にTRUE(1)を返す
81  */
82 bool become_random_artifact(player_type *player_ptr, object_type *o_ptr, bool a_scroll)
83 {
84     o_ptr->artifact_bias = 0;
85     o_ptr->name1 = 0;
86     o_ptr->name2 = 0;
87     for (int i = 0; i < TR_FLAG_SIZE; i++)
88         o_ptr->art_flags[i] |= k_info[o_ptr->k_idx].flags[i];
89
90     bool has_pval = FALSE;
91     if (o_ptr->pval)
92         has_pval = TRUE;
93
94     int warrior_artifact_bias = 0;
95     if (a_scroll && one_in_(4)) {
96         switch (player_ptr->pclass) {
97         case CLASS_WARRIOR:
98         case CLASS_BERSERKER:
99         case CLASS_ARCHER:
100         case CLASS_SAMURAI:
101         case CLASS_CAVALRY:
102         case CLASS_SMITH:
103             o_ptr->artifact_bias = BIAS_WARRIOR;
104             break;
105         case CLASS_MAGE:
106         case CLASS_HIGH_MAGE:
107         case CLASS_SORCERER:
108         case CLASS_MAGIC_EATER:
109         case CLASS_BLUE_MAGE:
110             o_ptr->artifact_bias = BIAS_MAGE;
111             break;
112         case CLASS_PRIEST:
113             o_ptr->artifact_bias = BIAS_PRIESTLY;
114             break;
115         case CLASS_ROGUE:
116         case CLASS_NINJA:
117             o_ptr->artifact_bias = BIAS_ROGUE;
118             warrior_artifact_bias = 25;
119             break;
120         case CLASS_RANGER:
121         case CLASS_SNIPER:
122             o_ptr->artifact_bias = BIAS_RANGER;
123             warrior_artifact_bias = 30;
124             break;
125         case CLASS_PALADIN:
126             o_ptr->artifact_bias = BIAS_PRIESTLY;
127             warrior_artifact_bias = 40;
128             break;
129         case CLASS_WARRIOR_MAGE:
130         case CLASS_RED_MAGE:
131             o_ptr->artifact_bias = BIAS_MAGE;
132             warrior_artifact_bias = 40;
133             break;
134         case CLASS_CHAOS_WARRIOR:
135             o_ptr->artifact_bias = BIAS_CHAOS;
136             warrior_artifact_bias = 40;
137             break;
138         case CLASS_MONK:
139         case CLASS_FORCETRAINER:
140             o_ptr->artifact_bias = BIAS_PRIESTLY;
141             break;
142         case CLASS_MINDCRAFTER:
143         case CLASS_BARD:
144             if (randint1(5) > 2)
145                 o_ptr->artifact_bias = BIAS_PRIESTLY;
146             break;
147         case CLASS_TOURIST:
148             if (randint1(5) > 2)
149                 o_ptr->artifact_bias = BIAS_WARRIOR;
150             break;
151         case CLASS_IMITATOR:
152             if (randint1(2) > 1)
153                 o_ptr->artifact_bias = BIAS_RANGER;
154             break;
155         case CLASS_BEASTMASTER:
156             o_ptr->artifact_bias = BIAS_CHR;
157             warrior_artifact_bias = 50;
158             break;
159         case CLASS_MIRROR_MASTER:
160             if (randint1(4) > 1) {
161                 o_ptr->artifact_bias = BIAS_MAGE;
162             } else {
163                 o_ptr->artifact_bias = BIAS_ROGUE;
164             }
165
166             break;
167         }
168     }
169
170     if (a_scroll && (randint1(100) <= warrior_artifact_bias))
171         o_ptr->artifact_bias = BIAS_WARRIOR;
172
173     GAME_TEXT new_name[1024];
174     strcpy(new_name, "");
175
176     bool a_cursed = FALSE;
177     if (!a_scroll && one_in_(A_CURSED))
178         a_cursed = TRUE;
179     if (((o_ptr->tval == TV_AMULET) || (o_ptr->tval == TV_RING)) && object_is_cursed(o_ptr))
180         a_cursed = TRUE;
181
182     int powers = randint1(5) + 1;
183     while (one_in_(powers) || one_in_(7) || one_in_(10))
184         powers++;
185
186     if (!a_cursed && one_in_(WEIRD_LUCK))
187         powers *= 2;
188
189     if (a_cursed)
190         powers /= 2;
191
192     int max_powers = powers;
193     int max_type = object_is_weapon_ammo(o_ptr) ? 7 : 5;
194     while (powers--) {
195         switch (randint1(max_type)) {
196         case 1:
197         case 2:
198             random_plus(o_ptr);
199             has_pval = TRUE;
200             break;
201         case 3:
202         case 4:
203             if (one_in_(2) && object_is_weapon_ammo(o_ptr) && (o_ptr->tval != TV_BOW)) {
204                 if (a_cursed && !one_in_(13))
205                     break;
206                 if (one_in_(13)) {
207                     if (one_in_(o_ptr->ds + 4))
208                         o_ptr->ds++;
209                 } else {
210                     if (one_in_(o_ptr->dd + 1))
211                         o_ptr->dd++;
212                 }
213             } else
214                 random_resistance(o_ptr);
215             break;
216         case 5:
217             random_misc(player_ptr, o_ptr);
218             break;
219         case 6:
220         case 7:
221             random_slay(o_ptr);
222             break;
223         default:
224             if (current_world_ptr->wizard)
225                 msg_print("Switch error in become_random_artifact!");
226             powers++;
227         }
228     };
229
230     if (has_pval) {
231         if (have_flag(o_ptr->art_flags, TR_BLOWS)) {
232             o_ptr->pval = randint1(2);
233             if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
234                 o_ptr->pval++;
235         } else {
236             do {
237                 o_ptr->pval++;
238             } while (o_ptr->pval < randint1(5) || one_in_(o_ptr->pval));
239         }
240
241         if ((o_ptr->pval > 4) && !one_in_(WEIRD_LUCK))
242             o_ptr->pval = 4;
243     }
244
245     if (object_is_armour(player_ptr, o_ptr))
246         o_ptr->to_a += randint1(o_ptr->to_a > 19 ? 1 : 20 - o_ptr->to_a);
247     else if (object_is_weapon_ammo(o_ptr)) {
248         o_ptr->to_h += randint1(o_ptr->to_h > 19 ? 1 : 20 - o_ptr->to_h);
249         o_ptr->to_d += randint1(o_ptr->to_d > 19 ? 1 : 20 - o_ptr->to_d);
250         if ((have_flag(o_ptr->art_flags, TR_WIS)) && (o_ptr->pval > 0))
251             add_flag(o_ptr->art_flags, TR_BLESSED);
252     }
253
254     add_flag(o_ptr->art_flags, TR_IGNORE_ACID);
255     add_flag(o_ptr->art_flags, TR_IGNORE_ELEC);
256     add_flag(o_ptr->art_flags, TR_IGNORE_FIRE);
257     add_flag(o_ptr->art_flags, TR_IGNORE_COLD);
258
259     s32b total_flags = flag_cost(player_ptr, o_ptr, o_ptr->pval);
260     if (a_cursed)
261         curse_artifact(player_ptr, o_ptr);
262
263     if (!a_cursed && one_in_(object_is_armour(player_ptr, o_ptr) ? ACTIVATION_CHANCE * 2 : ACTIVATION_CHANCE)) {
264         o_ptr->xtra2 = 0;
265         give_activation_power(o_ptr);
266     }
267
268     if (object_is_armour(player_ptr, o_ptr)) {
269         while ((o_ptr->to_d + o_ptr->to_h) > 20) {
270             if (one_in_(o_ptr->to_d) && one_in_(o_ptr->to_h))
271                 break;
272             o_ptr->to_d -= (HIT_POINT)randint0(3);
273             o_ptr->to_h -= (HIT_PROB)randint0(3);
274         }
275         while ((o_ptr->to_d + o_ptr->to_h) > 10) {
276             if (one_in_(o_ptr->to_d) || one_in_(o_ptr->to_h))
277                 break;
278             o_ptr->to_d -= (HIT_POINT)randint0(3);
279             o_ptr->to_h -= (HIT_PROB)randint0(3);
280         }
281     }
282
283     if (((o_ptr->artifact_bias == BIAS_MAGE) || (o_ptr->artifact_bias == BIAS_INT)) && (o_ptr->tval == TV_GLOVES))
284         add_flag(o_ptr->art_flags, TR_FREE_ACT);
285
286     if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) {
287         o_ptr->to_h = 0;
288         o_ptr->to_d = 0;
289         remove_flag(o_ptr->art_flags, TR_BLOWS);
290         remove_flag(o_ptr->art_flags, TR_FORCE_WEAPON);
291         remove_flag(o_ptr->art_flags, TR_SLAY_ANIMAL);
292         remove_flag(o_ptr->art_flags, TR_SLAY_EVIL);
293         remove_flag(o_ptr->art_flags, TR_SLAY_UNDEAD);
294         remove_flag(o_ptr->art_flags, TR_SLAY_DEMON);
295         remove_flag(o_ptr->art_flags, TR_SLAY_ORC);
296         remove_flag(o_ptr->art_flags, TR_SLAY_TROLL);
297         remove_flag(o_ptr->art_flags, TR_SLAY_GIANT);
298         remove_flag(o_ptr->art_flags, TR_SLAY_DRAGON);
299         remove_flag(o_ptr->art_flags, TR_KILL_DRAGON);
300         remove_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
301         remove_flag(o_ptr->art_flags, TR_VORPAL);
302         remove_flag(o_ptr->art_flags, TR_BRAND_POIS);
303         remove_flag(o_ptr->art_flags, TR_BRAND_ACID);
304         remove_flag(o_ptr->art_flags, TR_BRAND_ELEC);
305         remove_flag(o_ptr->art_flags, TR_BRAND_FIRE);
306         remove_flag(o_ptr->art_flags, TR_BRAND_COLD);
307     }
308
309     int power_level;
310     if (!object_is_weapon_ammo(o_ptr)) {
311         if (a_cursed)
312             power_level = 0;
313         else if (total_flags < 15000)
314             power_level = 1;
315         else if (total_flags < 35000)
316             power_level = 2;
317         else
318             power_level = 3;
319     } else {
320         if (a_cursed)
321             power_level = 0;
322         else if (total_flags < 20000)
323             power_level = 1;
324         else if (total_flags < 45000)
325             power_level = 2;
326         else
327             power_level = 3;
328     }
329
330     while (has_extreme_damage_rate(player_ptr, o_ptr) && !one_in_(SWORDFISH_LUCK))
331         weakening_artifact(player_ptr, o_ptr);
332
333     if (a_scroll) {
334         GAME_TEXT dummy_name[MAX_NLEN] = "";
335         concptr ask_msg = _("このアーティファクトを何と名付けますか?", "What do you want to call the artifact? ");
336         object_aware(player_ptr, o_ptr);
337         object_known(o_ptr);
338         o_ptr->ident |= IDENT_FULL_KNOWN;
339         o_ptr->art_name = quark_add("");
340         (void)screen_object(player_ptr, o_ptr, 0L);
341         if (!get_string(ask_msg, dummy_name, sizeof dummy_name) || !dummy_name[0]) {
342             /* Cancelled */
343             if (one_in_(2)) {
344                 get_table_sindarin_aux(dummy_name);
345             } else {
346                 get_table_name_aux(dummy_name);
347             }
348         }
349
350         sprintf(new_name, _("《%s》", "'%s'"), dummy_name);
351         chg_virtue(player_ptr, V_INDIVIDUALISM, 2);
352         chg_virtue(player_ptr, V_ENCHANT, 5);
353     } else {
354         get_random_name(o_ptr, new_name, object_is_armour(player_ptr, o_ptr), power_level);
355     }
356
357     o_ptr->art_name = quark_add(new_name);
358     msg_format_wizard(player_ptr, CHEAT_OBJECT,
359         _("パワー %d で 価値%ld のランダムアーティファクト生成 バイアスは「%s」", "Random artifact generated - Power:%d Value:%d Bias:%s."), max_powers,
360         total_flags, artifact_bias_name[o_ptr->artifact_bias]);
361     player_ptr->window |= PW_INVEN | PW_EQUIP;
362     return TRUE;
363 }