OSDN Git Service

[Refactor] #40561 Separated invest_modified_value() from become_random_artifact()
[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 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 bool decide_random_art_cursed(const bool a_scroll, object_type *o_ptr)
150 {
151     if (!a_scroll && one_in_(A_CURSED))
152         return TRUE;
153
154     if (((o_ptr->tval == TV_AMULET) || (o_ptr->tval == TV_RING)) && object_is_cursed(o_ptr))
155         return TRUE;
156
157     return FALSE;
158 }
159
160 static int decide_random_art_power(const bool a_cursed)
161 {
162     int powers = randint1(5) + 1;
163     while (one_in_(powers) || one_in_(7) || one_in_(10))
164         powers++;
165
166     if (!a_cursed && one_in_(WEIRD_LUCK))
167         powers *= 2;
168
169     if (a_cursed)
170         powers /= 2;
171
172     return powers;
173 }
174
175 static void invest_powers(player_type *player_ptr, object_type *o_ptr, int *powers, bool *has_pval, const bool a_cursed)
176 {
177     int max_type = object_is_weapon_ammo(o_ptr) ? 7 : 5;
178     while ((*powers)--) {
179         switch (randint1(max_type)) {
180         case 1:
181         case 2:
182             random_plus(o_ptr);
183             *has_pval = TRUE;
184             break;
185         case 3:
186         case 4:
187             if (one_in_(2) && object_is_weapon_ammo(o_ptr) && (o_ptr->tval != TV_BOW)) {
188                 if (a_cursed && !one_in_(13))
189                     break;
190                 if (one_in_(13)) {
191                     if (one_in_(o_ptr->ds + 4))
192                         o_ptr->ds++;
193                 } else {
194                     if (one_in_(o_ptr->dd + 1))
195                         o_ptr->dd++;
196                 }
197             } else
198                 random_resistance(o_ptr);
199
200             break;
201         case 5:
202             random_misc(player_ptr, o_ptr);
203             break;
204         case 6:
205         case 7:
206             random_slay(o_ptr);
207             break;
208         default:
209             if (current_world_ptr->wizard)
210                 msg_print("Switch error in become_random_artifact!");
211
212             (*powers)++;
213         }
214     };
215 }
216
217 static void strengthen_pval(object_type *o_ptr)
218 {
219     if (have_flag(o_ptr->art_flags, TR_BLOWS)) {
220         o_ptr->pval = randint1(2);
221         if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
222             o_ptr->pval++;
223     } else {
224         do {
225             o_ptr->pval++;
226         } while (o_ptr->pval < randint1(5) || one_in_(o_ptr->pval));
227     }
228
229     if ((o_ptr->pval > 4) && !one_in_(WEIRD_LUCK))
230         o_ptr->pval = 4;
231 }
232
233 /*!
234  * @brief 防具ならばAC修正、武具なら殺戮修正を付与する
235  * @param player_ptr プレーヤーへの参照ポインタ
236  * @param o_ptr ランダムアーティファクトを示すアイテムへの参照ポインタ
237  * @return なし
238  */
239 static void invest_modified_value(player_type *player_ptr, object_type *o_ptr)
240 {
241     if (object_is_armour(player_ptr, o_ptr)) {
242         o_ptr->to_a += randint1(o_ptr->to_a > 19 ? 1 : 20 - o_ptr->to_a);
243         return;
244     }
245     
246     if (!object_is_weapon_ammo(o_ptr))
247         return;
248
249     o_ptr->to_h += randint1(o_ptr->to_h > 19 ? 1 : 20 - o_ptr->to_h);
250     o_ptr->to_d += randint1(o_ptr->to_d > 19 ? 1 : 20 - o_ptr->to_d);
251     if ((have_flag(o_ptr->art_flags, TR_WIS)) && (o_ptr->pval > 0))
252         add_flag(o_ptr->art_flags, TR_BLESSED);
253 }
254
255 /*!
256  * @brief ランダムアーティファクト生成のメインルーチン
257  * @details 既に生成が済んでいるオブジェクトの構造体を、アーティファクトとして強化する。
258  * @param player_ptr プレーヤーへの参照ポインタ
259  * @param o_ptr 対象のオブジェクト構造体ポインタ
260  * @param a_scroll アーティファクト生成の巻物上の処理。呪いのアーティファクトが生成対象外となる。
261  * @return 常にTRUE(1)を返す
262  */
263 bool become_random_artifact(player_type *player_ptr, object_type *o_ptr, bool a_scroll)
264 {
265     o_ptr->artifact_bias = 0;
266     o_ptr->name1 = 0;
267     o_ptr->name2 = 0;
268     for (int i = 0; i < TR_FLAG_SIZE; i++)
269         o_ptr->art_flags[i] |= k_info[o_ptr->k_idx].flags[i];
270
271     bool has_pval = o_ptr->pval != 0;
272     int warrior_artifact_bias = 0;
273     if (a_scroll && one_in_(4))
274         set_artifact_bias(player_ptr, o_ptr, &warrior_artifact_bias);
275
276     if (a_scroll && (randint1(100) <= warrior_artifact_bias))
277         o_ptr->artifact_bias = BIAS_WARRIOR;
278
279     GAME_TEXT new_name[1024];
280     strcpy(new_name, "");
281
282     bool a_cursed = decide_random_art_cursed(a_scroll, o_ptr);
283     int powers = decide_random_art_power(a_cursed);
284     int max_powers = powers;
285     invest_powers(player_ptr, o_ptr, &powers, &has_pval, a_cursed);
286     if (has_pval)
287         strengthen_pval(o_ptr);
288
289     invest_modified_value(player_ptr, o_ptr);
290     add_flag(o_ptr->art_flags, TR_IGNORE_ACID);
291     add_flag(o_ptr->art_flags, TR_IGNORE_ELEC);
292     add_flag(o_ptr->art_flags, TR_IGNORE_FIRE);
293     add_flag(o_ptr->art_flags, TR_IGNORE_COLD);
294
295     s32b total_flags = flag_cost(player_ptr, o_ptr, o_ptr->pval);
296     if (a_cursed)
297         curse_artifact(player_ptr, o_ptr);
298
299     if (!a_cursed && one_in_(object_is_armour(player_ptr, o_ptr) ? ACTIVATION_CHANCE * 2 : ACTIVATION_CHANCE)) {
300         o_ptr->xtra2 = 0;
301         give_activation_power(o_ptr);
302     }
303
304     if (object_is_armour(player_ptr, o_ptr)) {
305         while ((o_ptr->to_d + o_ptr->to_h) > 20) {
306             if (one_in_(o_ptr->to_d) && one_in_(o_ptr->to_h))
307                 break;
308             o_ptr->to_d -= (HIT_POINT)randint0(3);
309             o_ptr->to_h -= (HIT_PROB)randint0(3);
310         }
311         while ((o_ptr->to_d + o_ptr->to_h) > 10) {
312             if (one_in_(o_ptr->to_d) || one_in_(o_ptr->to_h))
313                 break;
314             o_ptr->to_d -= (HIT_POINT)randint0(3);
315             o_ptr->to_h -= (HIT_PROB)randint0(3);
316         }
317     }
318
319     if (((o_ptr->artifact_bias == BIAS_MAGE) || (o_ptr->artifact_bias == BIAS_INT)) && (o_ptr->tval == TV_GLOVES))
320         add_flag(o_ptr->art_flags, TR_FREE_ACT);
321
322     if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_POISON_NEEDLE)) {
323         o_ptr->to_h = 0;
324         o_ptr->to_d = 0;
325         remove_flag(o_ptr->art_flags, TR_BLOWS);
326         remove_flag(o_ptr->art_flags, TR_FORCE_WEAPON);
327         remove_flag(o_ptr->art_flags, TR_SLAY_ANIMAL);
328         remove_flag(o_ptr->art_flags, TR_SLAY_EVIL);
329         remove_flag(o_ptr->art_flags, TR_SLAY_UNDEAD);
330         remove_flag(o_ptr->art_flags, TR_SLAY_DEMON);
331         remove_flag(o_ptr->art_flags, TR_SLAY_ORC);
332         remove_flag(o_ptr->art_flags, TR_SLAY_TROLL);
333         remove_flag(o_ptr->art_flags, TR_SLAY_GIANT);
334         remove_flag(o_ptr->art_flags, TR_SLAY_DRAGON);
335         remove_flag(o_ptr->art_flags, TR_KILL_DRAGON);
336         remove_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
337         remove_flag(o_ptr->art_flags, TR_VORPAL);
338         remove_flag(o_ptr->art_flags, TR_BRAND_POIS);
339         remove_flag(o_ptr->art_flags, TR_BRAND_ACID);
340         remove_flag(o_ptr->art_flags, TR_BRAND_ELEC);
341         remove_flag(o_ptr->art_flags, TR_BRAND_FIRE);
342         remove_flag(o_ptr->art_flags, TR_BRAND_COLD);
343     }
344
345     int power_level;
346     if (!object_is_weapon_ammo(o_ptr)) {
347         if (a_cursed)
348             power_level = 0;
349         else if (total_flags < 15000)
350             power_level = 1;
351         else if (total_flags < 35000)
352             power_level = 2;
353         else
354             power_level = 3;
355     } else {
356         if (a_cursed)
357             power_level = 0;
358         else if (total_flags < 20000)
359             power_level = 1;
360         else if (total_flags < 45000)
361             power_level = 2;
362         else
363             power_level = 3;
364     }
365
366     while (has_extreme_damage_rate(player_ptr, o_ptr) && !one_in_(SWORDFISH_LUCK))
367         weakening_artifact(player_ptr, o_ptr);
368
369     if (a_scroll) {
370         GAME_TEXT dummy_name[MAX_NLEN] = "";
371         concptr ask_msg = _("このアーティファクトを何と名付けますか?", "What do you want to call the artifact? ");
372         object_aware(player_ptr, o_ptr);
373         object_known(o_ptr);
374         o_ptr->ident |= IDENT_FULL_KNOWN;
375         o_ptr->art_name = quark_add("");
376         (void)screen_object(player_ptr, o_ptr, 0L);
377         if (!get_string(ask_msg, dummy_name, sizeof dummy_name) || !dummy_name[0]) {
378             /* Cancelled */
379             if (one_in_(2)) {
380                 get_table_sindarin_aux(dummy_name);
381             } else {
382                 get_table_name_aux(dummy_name);
383             }
384         }
385
386         sprintf(new_name, _("《%s》", "'%s'"), dummy_name);
387         chg_virtue(player_ptr, V_INDIVIDUALISM, 2);
388         chg_virtue(player_ptr, V_ENCHANT, 5);
389     } else {
390         get_random_name(o_ptr, new_name, object_is_armour(player_ptr, o_ptr), power_level);
391     }
392
393     o_ptr->art_name = quark_add(new_name);
394     msg_format_wizard(player_ptr, CHEAT_OBJECT,
395         _("パワー %d で 価値%ld のランダムアーティファクト生成 バイアスは「%s」", "Random artifact generated - Power:%d Value:%d Bias:%s."), max_powers,
396         total_flags, artifact_bias_name[o_ptr->artifact_bias]);
397     player_ptr->window |= PW_INVEN | PW_EQUIP;
398     return TRUE;
399 }