OSDN Git Service

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