OSDN Git Service

Merge pull request #716 from sikabane-works/release/3.0.0Alpha16
[hengbandforosx/hengbandosx.git] / src / object-enchant / apply-magic.cpp
1 /*!
2  * @brief ベースアイテムを強化する処理
3  * @date 2020/06/03
4  * @author Hourier
5  * @todo 少し長い。要分割
6  */
7
8 #include "object-enchant/apply-magic.h"
9 #include "artifact/fixed-art-types.h"
10 #include "artifact/fixed-art-generator.h"
11 #include "dungeon/dungeon.h"
12 #include "mutation/mutation-flag-types.h"
13 #include "object-enchant/apply-magic-accessory.h"
14 #include "object-enchant/apply-magic-armor.h"
15 #include "object-enchant/apply-magic-others.h"
16 #include "object-enchant/apply-magic-weapon.h"
17 #include "object-enchant/item-apply-magic.h"
18 #include "object-enchant/object-boost.h"
19 #include "object-enchant/object-curse.h"
20 #include "object-enchant/object-ego.h"
21 #include "object-enchant/special-object-flags.h"
22 #include "object-enchant/tr-types.h"
23 #include "object-enchant/trc-types.h"
24 #include "object-enchant/trg-types.h"
25 #include "object-hook/hook-checker.h"
26 #include "object-hook/hook-enchant.h"
27 #include "object/object-kind.h"
28 #include "player/player-status-flags.h"
29 #include "sv-definition/sv-armor-types.h"
30 #include "sv-definition/sv-protector-types.h"
31 #include "sv-definition/sv-weapon-types.h"
32 #include "system/artifact-type-definition.h"
33 #include "system/floor-type-definition.h"
34 #include "util/bit-flags-calculator.h"
35 #include "world/world.h"
36
37 /*!
38  * @brief 0 および負数に対応した randint1()
39  * @param n
40  *
41  * n == 0 のとき、常に 0 を返す。
42  * n >  0 のとき、[1, n] の乱数を返す。
43  * n <  0 のとき、[n,-1] の乱数を返す。
44  */
45 static int randint1_signed(const int n)
46 {
47     if (n == 0)
48         return 0;
49
50     return n > 0 ? randint1(n) : -randint1(-n);
51 }
52
53 /*!
54  * @brief 生成されたベースアイテムに魔法的な強化を与えるメインルーチン
55  * Complete the "creation" of an object by applying "magic" to the item
56  * @param owner_ptr プレーヤーへの参照ポインタ
57  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
58  * @param lev 生成基準階
59  * @param mode 生成オプション
60  * @return なし
61  * @details
62  * エゴ&アーティファクトの生成、呪い、pval強化
63  */
64 void apply_magic(player_type *owner_ptr, object_type *o_ptr, DEPTH lev, BIT_FLAGS mode)
65 {
66     if (owner_ptr->pseikaku == PERSONALITY_MUNCHKIN)
67         lev += randint0(owner_ptr->lev / 2 + 10);
68     if (lev > MAX_DEPTH - 1)
69         lev = MAX_DEPTH - 1;
70
71     int f1 = lev + 10;
72     if (f1 > d_info[owner_ptr->dungeon_idx].obj_good)
73         f1 = d_info[owner_ptr->dungeon_idx].obj_good;
74
75     int f2 = f1 * 2 / 3;
76     if ((owner_ptr->pseikaku != PERSONALITY_MUNCHKIN) && (f2 > d_info[owner_ptr->dungeon_idx].obj_great))
77         f2 = d_info[owner_ptr->dungeon_idx].obj_great;
78
79     if (has_good_luck(owner_ptr)) {
80         f1 += 5;
81         f2 += 2;
82     } else if (owner_ptr->muta.has(MUTA::BAD_LUCK)) {
83         f1 -= 5;
84         f2 -= 2;
85     }
86
87     int power = 0;
88     if ((mode & AM_GOOD) || magik(f1)) {
89         power = 1;
90         if ((mode & AM_GREAT) || magik(f2)) {
91             power = 2;
92             if (mode & AM_SPECIAL)
93                 power = 3;
94         }
95     } else if (magik(f1)) {
96         power = -1;
97         if (magik(f2))
98             power = -2;
99     }
100     if (mode & AM_CURSED) {
101         if (power > 0) {
102             power = 0 - power;
103         } else {
104             power--;
105         }
106     }
107
108     int rolls = 0;
109     if (power >= 2)
110         rolls = 1;
111
112     if (mode & (AM_GREAT | AM_SPECIAL))
113         rolls = 4;
114     if ((mode & AM_NO_FIXED_ART) || o_ptr->name1)
115         rolls = 0;
116
117     for (int i = 0; i < rolls; i++) {
118         if (make_artifact(owner_ptr, o_ptr))
119             break;
120         if (has_good_luck(owner_ptr) && one_in_(77)) {
121             if (make_artifact(owner_ptr, o_ptr))
122                 break;
123         }
124     }
125
126     if (object_is_fixed_artifact(o_ptr)) {
127         artifact_type *a_ptr = apply_artifact(owner_ptr, o_ptr);
128         a_ptr->cur_num = 1;
129         if (current_world_ptr->character_dungeon)
130             a_ptr->floor_id = owner_ptr->floor_id;
131         return;
132     }
133
134     switch (o_ptr->tval) {
135     case TV_DIGGING:
136     case TV_HAFTED:
137     case TV_BOW:
138     case TV_SHOT:
139     case TV_ARROW:
140     case TV_BOLT: {
141         if (power)
142             apply_magic_weapon(owner_ptr, o_ptr, lev, power);
143         break;
144     }
145     case TV_POLEARM: {
146         if (power && !(o_ptr->sval == SV_DEATH_SCYTHE))
147             apply_magic_weapon(owner_ptr, o_ptr, lev, power);
148         break;
149     }
150     case TV_SWORD: {
151         if (power && !(o_ptr->sval == SV_POISON_NEEDLE))
152             apply_magic_weapon(owner_ptr, o_ptr, lev, power);
153         break;
154     }
155     case TV_DRAG_ARMOR:
156     case TV_HARD_ARMOR:
157     case TV_SOFT_ARMOR:
158     case TV_SHIELD:
159     case TV_HELM:
160     case TV_CROWN:
161     case TV_CLOAK:
162     case TV_GLOVES:
163     case TV_BOOTS: {
164         if (((o_ptr->tval == TV_CLOAK) && (o_ptr->sval == SV_ELVEN_CLOAK)) || ((o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_KUROSHOUZOKU)))
165             o_ptr->pval = randint1(4);
166
167         if (power || ((o_ptr->tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM)) || ((o_ptr->tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
168             || ((o_ptr->tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
169             || ((o_ptr->tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE)))
170             apply_magic_armor(owner_ptr, o_ptr, lev, power);
171
172         break;
173     }
174     case TV_RING:
175     case TV_AMULET: {
176         if (!power && (randint0(100) < 50))
177             power = -1;
178         apply_magic_accessary(owner_ptr, o_ptr, lev, power);
179         break;
180     }
181     default: {
182         apply_magic_others(owner_ptr, o_ptr, power);
183         break;
184     }
185     }
186
187     if ((o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_ABUNAI_MIZUGI) && (owner_ptr->pseikaku == PERSONALITY_SEXY)) {
188         o_ptr->pval = 3;
189         add_flag(o_ptr->art_flags, TR_STR);
190         add_flag(o_ptr->art_flags, TR_INT);
191         add_flag(o_ptr->art_flags, TR_WIS);
192         add_flag(o_ptr->art_flags, TR_DEX);
193         add_flag(o_ptr->art_flags, TR_CON);
194         add_flag(o_ptr->art_flags, TR_CHR);
195     }
196
197     if (object_is_ego(o_ptr)) {
198         ego_item_type *e_ptr = &e_info[o_ptr->name2];
199         if (!e_ptr->cost)
200             o_ptr->ident |= (IDENT_BROKEN);
201
202         if (e_ptr->gen_flags.has(TRG::CURSED))
203             o_ptr->curse_flags |= (TRC_CURSED);
204         if (e_ptr->gen_flags.has(TRG::HEAVY_CURSE))
205             o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
206         if (e_ptr->gen_flags.has(TRG::PERMA_CURSE))
207             o_ptr->curse_flags |= (TRC_PERMA_CURSE);
208         if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
209             o_ptr->curse_flags |= get_curse(owner_ptr, 0, o_ptr);
210         if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
211             o_ptr->curse_flags |= get_curse(owner_ptr, 1, o_ptr);
212         if (e_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
213             o_ptr->curse_flags |= get_curse(owner_ptr, 2, o_ptr);
214
215         if (e_ptr->gen_flags.has(TRG::ONE_SUSTAIN))
216             one_sustain(o_ptr);
217         if (e_ptr->gen_flags.has(TRG::XTRA_POWER))
218             one_ability(o_ptr);
219         if (e_ptr->gen_flags.has(TRG::XTRA_H_RES))
220             one_high_resistance(o_ptr);
221         if (e_ptr->gen_flags.has(TRG::XTRA_E_RES))
222             one_ele_resistance(o_ptr);
223         if (e_ptr->gen_flags.has(TRG::XTRA_D_RES))
224             one_dragon_ele_resistance(o_ptr);
225         if (e_ptr->gen_flags.has(TRG::XTRA_L_RES))
226             one_lordly_high_resistance(o_ptr);
227         if (e_ptr->gen_flags.has(TRG::XTRA_RES))
228             one_resistance(o_ptr);
229         if (e_ptr->gen_flags.has(TRG::XTRA_DICE)) {
230             do {
231                 o_ptr->dd++;
232             } while (one_in_(o_ptr->dd));
233
234             if (o_ptr->dd > 9)
235                 o_ptr->dd = 9;
236         }
237
238         if (e_ptr->act_idx)
239             o_ptr->xtra2 = (XTRA8)e_ptr->act_idx;
240
241         bool is_powerful = e_ptr->gen_flags.has(TRG::POWERFUL);
242
243         if ((object_is_cursed(o_ptr) || object_is_broken(o_ptr)) && !is_powerful) {
244             if (e_ptr->max_to_h)
245                 o_ptr->to_h -= randint1(e_ptr->max_to_h);
246             if (e_ptr->max_to_d)
247                 o_ptr->to_d -= randint1(e_ptr->max_to_d);
248             if (e_ptr->max_to_a)
249                 o_ptr->to_a -= randint1(e_ptr->max_to_a);
250             if (e_ptr->max_pval)
251                 o_ptr->pval -= randint1(e_ptr->max_pval);
252         } else {
253             if (is_powerful) {
254                 if (e_ptr->max_to_h > 0 && o_ptr->to_h < 0)
255                     o_ptr->to_h = 0 - o_ptr->to_h;
256                 if (e_ptr->max_to_d > 0 && o_ptr->to_d < 0)
257                     o_ptr->to_d = 0 - o_ptr->to_d;
258                 if (e_ptr->max_to_a > 0 && o_ptr->to_a < 0)
259                     o_ptr->to_a = 0 - o_ptr->to_a;
260             }
261
262             o_ptr->to_h += (HIT_PROB)randint1_signed(e_ptr->max_to_h);
263             o_ptr->to_d += randint1_signed(e_ptr->max_to_d);
264             o_ptr->to_a += (ARMOUR_CLASS)randint1_signed(e_ptr->max_to_a);
265
266             if (o_ptr->name2 == EGO_ACCURACY) {
267                 while (o_ptr->to_h < o_ptr->to_d + 10) {
268                     o_ptr->to_h += 5;
269                     o_ptr->to_d -= 5;
270                 }
271                 o_ptr->to_h = MAX(o_ptr->to_h, 15);
272             }
273
274             if (o_ptr->name2 == EGO_VELOCITY) {
275                 while (o_ptr->to_d < o_ptr->to_h + 10) {
276                     o_ptr->to_d += 5;
277                     o_ptr->to_h -= 5;
278                 }
279                 o_ptr->to_d = MAX(o_ptr->to_d, 15);
280             }
281
282             if ((o_ptr->name2 == EGO_PROTECTION) || (o_ptr->name2 == EGO_S_PROTECTION) || (o_ptr->name2 == EGO_H_PROTECTION)) {
283                 o_ptr->to_a = MAX(o_ptr->to_a, 15);
284             }
285
286             if (e_ptr->max_pval) {
287                 if ((o_ptr->name2 == EGO_HA) && (has_flag(o_ptr->art_flags, TR_BLOWS))) {
288                     o_ptr->pval++;
289                     if ((lev > 60) && one_in_(3) && ((o_ptr->dd * (o_ptr->ds + 1)) < 15))
290                         o_ptr->pval++;
291                 } else if (o_ptr->name2 == EGO_DEMON) {
292                     if (has_flag(o_ptr->art_flags, TR_BLOWS)) {
293                         o_ptr->pval += randint1(2);
294                     } else {
295                         o_ptr->pval += randint1(e_ptr->max_pval);
296                     }
297                 } else if (o_ptr->name2 == EGO_ATTACKS) {
298                     o_ptr->pval = randint1(e_ptr->max_pval * lev / 100 + 1);
299                     if (o_ptr->pval > 3)
300                         o_ptr->pval = 3;
301                     if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA))
302                         o_ptr->pval += randint1(2);
303                 } else if (o_ptr->name2 == EGO_BAT) {
304                     o_ptr->pval = randint1(e_ptr->max_pval);
305                     if (o_ptr->sval == SV_ELVEN_CLOAK)
306                         o_ptr->pval += randint1(2);
307                 } else if (o_ptr->name2 == EGO_A_DEMON || o_ptr->name2 == EGO_DRUID || o_ptr->name2 == EGO_OLOG) {
308                     o_ptr->pval = randint1(e_ptr->max_pval);
309                 } else {
310                     if (e_ptr->max_pval > 0)
311                         o_ptr->pval += randint1(e_ptr->max_pval);
312                     else if (e_ptr->max_pval < 0)
313                         o_ptr->pval -= randint1(0 - e_ptr->max_pval);
314                 }
315             }
316
317             if ((o_ptr->name2 == EGO_SPEED) && (lev < 50)) {
318                 o_ptr->pval = randint1(o_ptr->pval);
319             }
320
321             if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_HAYABUSA) && (o_ptr->pval > 2) && (o_ptr->name2 != EGO_ATTACKS))
322                 o_ptr->pval = 2;
323         }
324
325         return;
326     }
327
328     if (o_ptr->k_idx) {
329         object_kind *k_ptr = &k_info[o_ptr->k_idx];
330         if (!k_info[o_ptr->k_idx].cost)
331             o_ptr->ident |= (IDENT_BROKEN);
332
333         if (k_ptr->gen_flags.has(TRG::CURSED))
334             o_ptr->curse_flags |= (TRC_CURSED);
335         if (k_ptr->gen_flags.has(TRG::HEAVY_CURSE))
336             o_ptr->curse_flags |= TRC_HEAVY_CURSE;
337         if (k_ptr->gen_flags.has(TRG::PERMA_CURSE))
338             o_ptr->curse_flags |= TRC_PERMA_CURSE;
339         if (k_ptr->gen_flags.has(TRG::RANDOM_CURSE0))
340             o_ptr->curse_flags |= get_curse(owner_ptr, 0, o_ptr);
341         if (k_ptr->gen_flags.has(TRG::RANDOM_CURSE1))
342             o_ptr->curse_flags |= get_curse(owner_ptr, 1, o_ptr);
343         if (k_ptr->gen_flags.has(TRG::RANDOM_CURSE2))
344             o_ptr->curse_flags |= get_curse(owner_ptr, 2, o_ptr);
345     }
346 }