OSDN Git Service

fd4c78280ffa5dc141d3ea7d415f5618d324f255
[hengbandforosx/hengbandosx.git] / src / object-enchant / apply-magic-amulet.cpp
1 /*!
2  * @brief アミュレットを強化生成する処理
3  * @date 2021/04/30
4  * @author Hourier
5  */
6
7 #include "object-enchant/apply-magic-amulet.h"
8 #include "artifact/random-art-generator.h"
9 #include "object-enchant/object-boost.h"
10 #include "object-enchant/object-ego.h"
11 #include "object-enchant/special-object-flags.h"
12 #include "object-enchant/trc-types.h"
13 #include "object-hook/hook-checker.h"
14 #include "object/object-kind.h"
15 #include "sv-definition/sv-amulet-types.h"
16 #include "system/object-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "util/bit-flags-calculator.h"
19
20 /*
21  * @brief コンストラクタ
22  * @param owner_ptr プレーヤーへの参照ポインタ
23  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
24  * @param level 生成基準階
25  * @param power 生成ランク
26  */
27 AmuletEnchanter::AmuletEnchanter(player_type *owner_ptr, object_type *o_ptr, DEPTH level, int power)
28     : owner_ptr(owner_ptr)
29     , o_ptr(o_ptr)
30     , level(level)
31     , power(power)
32 {
33 }
34
35 /*!
36  * @brief アミュレットに生成ランクごとの強化を与える
37  * Apply magic to an item known to be a "ring" or "amulet"
38  * @param owner_ptr プレーヤーへの参照ポインタ
39  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
40  * @param level 生成基準階
41  * @param power 生成ランク
42  * @return なし
43  * @details power > 2 is debug only
44  */
45 void AmuletEnchanter::apply_magic()
46 {
47     enchant();
48     if ((one_in_(150) && (this->power > 0) && !object_is_cursed(this->o_ptr) && (this->level > 79)) || (this->power > 2)) {
49         this->o_ptr->pval = MIN(this->o_ptr->pval, 4);
50         become_random_artifact(owner_ptr, this->o_ptr, false);
51         return;
52     }
53
54     if ((this->power == 2) && one_in_(2)) {
55         give_ego_index();
56         this->o_ptr->curse_flags.clear();
57         return;
58     }
59
60     if ((this->power == -2) && one_in_(2)) {
61         give_cursed();
62         return;
63     }
64 }
65
66 void AmuletEnchanter::enchant()
67 {
68     switch (this->o_ptr->sval) {
69     case SV_AMULET_INTELLIGENCE:
70     case SV_AMULET_WISDOM:
71     case SV_AMULET_CHARISMA:
72         this->o_ptr->pval = 1 + (PARAMETER_VALUE)m_bonus(5, this->level);
73         if (this->power < 0) {
74             set_bits(this->o_ptr->ident, IDENT_BROKEN);
75             this->o_ptr->curse_flags.set(TRC::CURSED);
76             this->o_ptr->pval = 0 - this->o_ptr->pval;
77         }
78
79         break;
80     case SV_AMULET_BRILLIANCE:
81         this->o_ptr->pval = 1 + m_bonus(3, this->level);
82         if (one_in_(4)) {
83             this->o_ptr->pval++;
84         }
85
86         if (this->power < 0) {
87             set_bits(this->o_ptr->ident, IDENT_BROKEN);
88             this->o_ptr->curse_flags.set(TRC::CURSED);
89             this->o_ptr->pval = 0 - this->o_ptr->pval;
90         }
91
92         break;
93     case SV_AMULET_NO_MAGIC:
94     case SV_AMULET_NO_TELE:
95         if (this->power < 0) {
96             this->o_ptr->curse_flags.set(TRC::CURSED);
97         }
98
99         break;
100     case SV_AMULET_RESISTANCE:
101         if (one_in_(5)) {
102             one_high_resistance(this->o_ptr);
103         }
104
105         if (one_in_(5)) {
106             add_flag(this->o_ptr->art_flags, TR_RES_POIS);
107         }
108
109         break;
110     case SV_AMULET_SEARCHING:
111         this->o_ptr->pval = 2 + randint1(6);
112         if (this->power >= 0) {
113             add_esp_weak(this->o_ptr, false);
114             break;
115         }
116
117         set_bits(this->o_ptr->ident, IDENT_BROKEN);
118         this->o_ptr->curse_flags.set(TRC::CURSED);
119         this->o_ptr->pval = 0 - (this->o_ptr->pval);
120         break;
121     case SV_AMULET_THE_MAGI:
122         this->o_ptr->pval = randint1(5) + (PARAMETER_VALUE)m_bonus(5, this->level);
123         this->o_ptr->to_a = randint1(5) + (ARMOUR_CLASS)m_bonus(5, this->level);
124         add_esp_weak(this->o_ptr, false);
125         break;
126     case SV_AMULET_DOOM:
127         set_bits(this->o_ptr->ident, IDENT_BROKEN);
128         this->o_ptr->curse_flags.set(TRC::CURSED);
129         this->o_ptr->pval = 0 - (randint1(5) + (PARAMETER_VALUE)m_bonus(5, this->level));
130         this->o_ptr->to_a = 0 - (randint1(5) + (ARMOUR_CLASS)m_bonus(5, this->level));
131         if (this->power > 0) {
132             this->power = 0 - this->power;
133         }
134
135         break;
136     case SV_AMULET_MAGIC_MASTERY:
137         this->o_ptr->pval = 1 + (PARAMETER_VALUE)m_bonus(4, this->level);
138         if (this->power >= 0) {
139             break;
140         }
141
142         set_bits(this->o_ptr->ident, IDENT_BROKEN);
143         this->o_ptr->curse_flags.set(TRC::CURSED);
144         this->o_ptr->pval = 0 - this->o_ptr->pval;
145         break;
146     }
147 }
148
149 void AmuletEnchanter::give_ego_index()
150 {
151     while (!this->o_ptr->name2) {
152         auto *k_ptr = &k_info[this->o_ptr->k_idx];
153         switch (randint1(21)) {
154         case 1:
155         case 2:
156             if (has_flag(k_ptr->flags, TR_SLOW_DIGEST)) {
157                 break;
158             }
159
160             this->o_ptr->name2 = EGO_AMU_SLOW_D;
161             break;
162         case 3:
163         case 4:
164             if (this->o_ptr->pval) {
165                 break;
166             }
167
168             this->o_ptr->name2 = EGO_AMU_INFRA;
169             break;
170         case 5:
171         case 6:
172             if (has_flag(k_ptr->flags, TR_SEE_INVIS)) {
173                 break;
174             }
175
176             this->o_ptr->name2 = EGO_AMU_SEE_INVIS;
177             break;
178         case 7:
179         case 8:
180             if (has_flag(k_ptr->flags, TR_HOLD_EXP)) {
181                 break;
182             }
183
184             this->o_ptr->name2 = EGO_AMU_HOLD_EXP;
185             break;
186         case 9:
187             if (has_flag(k_ptr->flags, TR_LEVITATION)) {
188                 break;
189             }
190
191             this->o_ptr->name2 = EGO_AMU_LEVITATION;
192             break;
193         case 10:
194         case 11:
195         case 21:
196             this->o_ptr->name2 = EGO_AMU_AC;
197             break;
198         case 12:
199             if (has_flag(k_ptr->flags, TR_RES_FIRE)) {
200                 break;
201             }
202
203             if (m_bonus(10, this->level) > 8) {
204                 this->o_ptr->name2 = EGO_AMU_RES_FIRE_;
205                 break;
206             }
207
208             this->o_ptr->name2 = EGO_AMU_RES_FIRE;
209             break;
210         case 13:
211             if (has_flag(k_ptr->flags, TR_RES_COLD)) {
212                 break;
213             }
214
215             if (m_bonus(10, this->level) > 8) {
216                 this->o_ptr->name2 = EGO_AMU_RES_COLD_;
217                 break;
218             }
219
220             this->o_ptr->name2 = EGO_AMU_RES_COLD;
221             break;
222         case 14:
223             if (has_flag(k_ptr->flags, TR_RES_ELEC)) {
224                 break;
225             }
226
227             if (m_bonus(10, this->level) > 8) {
228                 this->o_ptr->name2 = EGO_AMU_RES_ELEC_;
229                 break;
230             }
231
232             this->o_ptr->name2 = EGO_AMU_RES_ELEC;
233             break;
234         case 15:
235             if (has_flag(k_ptr->flags, TR_RES_ACID)) {
236                 break;
237             }
238
239             if (m_bonus(10, this->level) > 8) {
240                 this->o_ptr->name2 = EGO_AMU_RES_ACID_;
241                 break;
242             }
243
244             this->o_ptr->name2 = EGO_AMU_RES_ACID;
245             break;
246         case 16:
247         case 17:
248         case 18:
249         case 19:
250         case 20:
251             give_high_ego_index();
252             break;
253         }
254     }
255 }
256
257 void AmuletEnchanter::give_high_ego_index()
258 {
259     switch (this->o_ptr->sval) {
260     case SV_AMULET_TELEPORT:
261         if (m_bonus(10, this->level) > 9) {
262             this->o_ptr->name2 = EGO_AMU_D_DOOR;
263             break;
264         }
265
266         if (one_in_(2)) {
267             this->o_ptr->name2 = EGO_AMU_JUMP;
268             break;
269         }
270
271         this->o_ptr->name2 = EGO_AMU_TELEPORT;
272         break;
273     case SV_AMULET_RESIST_ACID:
274         if ((m_bonus(10, this->level) > 6) && one_in_(2)) {
275             this->o_ptr->name2 = EGO_AMU_RES_ACID_;
276         }
277
278         break;
279     case SV_AMULET_SEARCHING:
280         this->o_ptr->name2 = EGO_AMU_STEALTH;
281         break;
282     case SV_AMULET_BRILLIANCE:
283         if (!one_in_(3)) {
284             break;
285         }
286
287         this->o_ptr->name2 = EGO_AMU_IDENT;
288         break;
289     case SV_AMULET_CHARISMA:
290         if (!one_in_(3)) {
291             break;
292         }
293
294         this->o_ptr->name2 = EGO_AMU_CHARM;
295         break;
296     case SV_AMULET_THE_MAGI:
297         if (one_in_(2)) {
298             break;
299         }
300
301         this->o_ptr->name2 = EGO_AMU_GREAT;
302         break;
303     case SV_AMULET_RESISTANCE:
304         if (!one_in_(5)) {
305             break;
306         }
307
308         this->o_ptr->name2 = EGO_AMU_DEFENDER;
309         break;
310     case SV_AMULET_TELEPATHY:
311         if (!one_in_(3)) {
312             break;
313         }
314
315         this->o_ptr->name2 = EGO_AMU_DETECTION;
316         break;
317     default:
318         break;
319     }
320 }
321
322 void AmuletEnchanter::give_cursed()
323 {
324     if (this->o_ptr->to_h > 0) {
325         this->o_ptr->to_h = 0 - this->o_ptr->to_h;
326     }
327
328     if (this->o_ptr->to_d > 0) {
329         this->o_ptr->to_d = 0 - this->o_ptr->to_d;
330     }
331
332     if (this->o_ptr->to_a > 0) {
333         this->o_ptr->to_a = 0 - this->o_ptr->to_a;
334     }
335
336     if (this->o_ptr->pval > 0) {
337         this->o_ptr->pval = 0 - this->o_ptr->pval;
338     }
339
340     this->o_ptr->art_flags[0] = 0;
341     this->o_ptr->art_flags[1] = 0;
342     while (!this->o_ptr->name2) {
343         auto *k_ptr = &k_info[this->o_ptr->k_idx];
344         switch (randint1(5)) {
345         case 1:
346             if (has_flag(k_ptr->flags, TR_DRAIN_EXP)) {
347                 break;
348             }
349
350             this->o_ptr->name2 = EGO_AMU_DRAIN_EXP;
351             break;
352         case 2:
353             this->o_ptr->name2 = EGO_AMU_FOOL;
354             break;
355         case 3:
356             if (has_flag(k_ptr->flags, TR_AGGRAVATE)) {
357                 break;
358             }
359
360             this->o_ptr->name2 = EGO_AMU_AGGRAVATE;
361             break;
362         case 4:
363             if (has_flag(k_ptr->flags, TR_TY_CURSE)) {
364                 break;
365             }
366
367             this->o_ptr->name2 = EGO_AMU_TY_CURSE;
368             break;
369         case 5:
370             this->o_ptr->name2 = EGO_AMU_NAIVETY;
371             break;
372         }
373     }
374
375     set_bits(this->o_ptr->ident, IDENT_BROKEN);
376     this->o_ptr->curse_flags.set({ TRC::CURSED, TRC::HEAVY_CURSE });
377 }