OSDN Git Service

ec2faa33d2db2a51be00274ac690b3d0b648ecb6
[hengbandforosx/hengbandosx.git] / src / spell-kind / spells-random.cpp
1 /*!
2  * @brief ダイス目により様々な効果を及ぼす魔法の処理
3  * @date 2020/06/05
4  * @author Hourier
5  */
6
7 #include "spell-kind/spells-random.h"
8 #include "avatar/avatar.h"
9 #include "effect/attribute-types.h"
10 #include "effect/effect-characteristics.h"
11 #include "effect/effect-processor.h"
12 #include "hpmp/hp-mp-processor.h"
13 #include "monster-floor/monster-summon.h"
14 #include "monster-floor/place-monster-types.h"
15 #include "mutation/mutation-investor-remover.h"
16 #include "player-base/player-class.h"
17 #include "player/player-damage.h"
18 #include "spell-kind/earthquake.h"
19 #include "spell-kind/spells-equipment.h"
20 #include "spell-kind/spells-floor.h"
21 #include "spell-kind/spells-genocide.h"
22 #include "spell-kind/spells-launcher.h"
23 #include "spell-kind/spells-lite.h"
24 #include "spell-kind/spells-neighbor.h"
25 #include "spell-kind/spells-sight.h"
26 #include "spell-kind/spells-specific-bolt.h"
27 #include "spell-kind/spells-teleport.h"
28 #include "spell/spells-diceroll.h"
29 #include "spell/spells-status.h"
30 #include "spell/spells-summon.h"
31 #include "spell/summon-types.h"
32 #include "status/bad-status-setter.h"
33 #include "status/base-status.h"
34 #include "status/experience.h"
35 #include "system/floor-type-definition.h"
36 #include "system/player-type-definition.h"
37 #include "target/target-getter.h"
38 #include "view/display-messages.h"
39
40 /*!
41  * @brief 混沌招来処理
42  * @return 作用が実際にあった場合TRUEを返す
43  */
44 void call_chaos(PlayerType *player_ptr)
45 {
46     AttributeType hurt_types[32] = { AttributeType::ELEC, AttributeType::POIS, AttributeType::ACID, AttributeType::COLD, AttributeType::FIRE,
47         AttributeType::MISSILE, AttributeType::PLASMA, AttributeType::HOLY_FIRE, AttributeType::WATER, AttributeType::LITE,
48         AttributeType::DARK, AttributeType::FORCE, AttributeType::INERTIAL, AttributeType::MANA, AttributeType::METEOR, AttributeType::ICE,
49         AttributeType::CHAOS, AttributeType::NETHER, AttributeType::DISENCHANT, AttributeType::SHARDS, AttributeType::SOUND, AttributeType::NEXUS,
50         AttributeType::CONFUSION, AttributeType::TIME, AttributeType::GRAVITY, AttributeType::ROCKET, AttributeType::NUKE, AttributeType::HELL_FIRE,
51         AttributeType::DISINTEGRATE, AttributeType::PSY_SPEAR, AttributeType::VOID_MAGIC, AttributeType::ABYSS };
52
53     AttributeType chaos_type = hurt_types[randint0(32)];
54     bool line_chaos = false;
55     if (one_in_(4))
56         line_chaos = true;
57
58     int dir;
59     if (one_in_(6)) {
60         for (int dummy = 1; dummy < 10; dummy++) {
61             if (dummy - 5) {
62                 if (line_chaos)
63                     fire_beam(player_ptr, chaos_type, dummy, 150);
64                 else
65                     fire_ball(player_ptr, chaos_type, dummy, 150, 2);
66             }
67         }
68
69         return;
70     }
71
72     if (one_in_(3)) {
73         fire_ball(player_ptr, chaos_type, 0, 500, 8);
74         return;
75     }
76
77     if (!get_aim_dir(player_ptr, &dir))
78         return;
79     if (line_chaos)
80         fire_beam(player_ptr, chaos_type, dir, 250);
81     else
82         fire_ball(player_ptr, chaos_type, dir, 250, 3 + (player_ptr->lev / 35));
83 }
84
85 /*!
86  * @brief TY_CURSE処理発動 / Activate the evil Topi Ylinen curse
87  * @param player_ptr プレイヤーへの参照ポインタ
88  * @param stop_ty 再帰処理停止フラグ
89  * @param count 発動回数
90  * @return 作用が実際にあった場合TRUEを返す
91  * @details
92  * <pre>
93  * rr9: Stop the nasty things when a Cyberdemon is summoned
94  * or the player gets paralyzed.
95  * </pre>
96  */
97 bool activate_ty_curse(PlayerType *player_ptr, bool stop_ty, int *count)
98 {
99     BIT_FLAGS flg = (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP);
100     bool is_first_curse = true;
101     auto *floor_ptr = player_ptr->current_floor_ptr;
102     while (is_first_curse || (one_in_(3) && !stop_ty)) {
103         is_first_curse = false;
104         switch (randint1(34)) {
105         case 28:
106         case 29:
107             if (!(*count)) {
108                 msg_print(_("地面が揺れた...", "The ground trembles..."));
109                 earthquake(player_ptr, player_ptr->y, player_ptr->x, 5 + randint0(10), 0);
110                 if (!one_in_(6))
111                     break;
112             }
113             /* Fall through */
114         case 30:
115         case 31:
116             if (!(*count)) {
117                 HIT_POINT dam = damroll(10, 10);
118                 msg_print(_("純粋な魔力の次元への扉が開いた!", "A portal opens to a plane of raw mana!"));
119                 project(player_ptr, 0, 8, player_ptr->y, player_ptr->x, dam, AttributeType::MANA, flg);
120                 take_hit(player_ptr, DAMAGE_NOESCAPE, dam, _("純粋な魔力の解放", "released pure mana"));
121                 if (!one_in_(6))
122                     break;
123             }
124             /* Fall through */
125         case 32:
126         case 33:
127             if (!(*count)) {
128                 msg_print(_("周囲の空間が歪んだ!", "Space warps about you!"));
129                 teleport_player(player_ptr, damroll(10, 10), TELEPORT_PASSIVE);
130                 if (randint0(13))
131                     (*count) += activate_hi_summon(player_ptr, player_ptr->y, player_ptr->x, false);
132                 if (!one_in_(6))
133                     break;
134             }
135             /* Fall through */
136         case 34:
137             msg_print(_("エネルギーのうねりを感じた!", "You feel a surge of energy!"));
138             wall_breaker(player_ptr);
139             if (!randint0(7)) {
140                 project(player_ptr, 0, 7, player_ptr->y, player_ptr->x, 50, AttributeType::KILL_WALL, flg);
141                 take_hit(player_ptr, DAMAGE_NOESCAPE, 50, _("エネルギーのうねり", "surge of energy"));
142             }
143
144             if (!one_in_(6))
145                 break;
146             /* Fall through */
147         case 1:
148         case 2:
149         case 3:
150         case 16:
151         case 17:
152             aggravate_monsters(player_ptr, 0);
153             if (!one_in_(6))
154                 break;
155             /* Fall through */
156         case 4:
157         case 5:
158         case 6:
159             (*count) += activate_hi_summon(player_ptr, player_ptr->y, player_ptr->x, false);
160             if (!one_in_(6))
161                 break;
162             /* Fall through */
163         case 7:
164         case 8:
165         case 9:
166         case 18:
167             (*count) += summon_specific(
168                 player_ptr, 0, player_ptr->y, player_ptr->x, floor_ptr->dun_level, SUMMON_NONE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
169             if (!one_in_(6))
170                 break;
171             /* Fall through */
172         case 10:
173         case 11:
174         case 12:
175             msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away..."));
176             lose_exp(player_ptr, player_ptr->exp / 16);
177             if (!one_in_(6))
178                 break;
179             /* Fall through */
180         case 13:
181         case 14:
182         case 15:
183         case 19:
184         case 20: {
185             auto is_statue = stop_ty;
186             is_statue |= player_ptr->free_act && (randint1(125) < player_ptr->skill_sav);
187             is_statue |= PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER);
188             if (!is_statue) {
189                 msg_print(_("彫像になった気分だ!", "You feel like a statue!"));
190                 TIME_EFFECT turns = player_ptr->free_act ? randint1(3) : randint1(13);
191                 (void)BadStatusSetter(player_ptr).mod_paralysis(turns);
192                 stop_ty = true;
193             }
194
195             if (!one_in_(6)) {
196                 break;
197             }
198         }
199             /* Fall through */
200         case 21:
201         case 22:
202         case 23:
203             (void)do_dec_stat(player_ptr, randint0(6));
204             if (!one_in_(6))
205                 break;
206             /* Fall through */
207         case 24:
208             msg_print(_("ほえ?私は誰?ここで何してる?", "Huh? Who am I? What am I doing here?"));
209             lose_all_info(player_ptr);
210             if (!one_in_(6))
211                 break;
212             /* Fall through */
213         case 25:
214             if ((floor_ptr->dun_level > 65) && !stop_ty) {
215                 (*count) += summon_cyber(player_ptr, -1, player_ptr->y, player_ptr->x);
216                 stop_ty = true;
217                 break;
218             }
219
220             if (!one_in_(6))
221                 break;
222             /* Fall through */
223         default:
224             for (int i = 0; i < A_MAX; i++) {
225                 do {
226                     (void)do_dec_stat(player_ptr, i);
227                 } while (one_in_(2));
228             }
229         }
230     }
231
232     return stop_ty;
233 }
234
235 /*!
236  * @brief 運命の輪、並びにカオス的な効果の発動
237  * @param player_ptr プレイヤーへの参照ポインタ
238  * @param spell ランダムな効果を選択するための基準ID
239  */
240 void wild_magic(PlayerType *player_ptr, int spell)
241 {
242     int type = SUMMON_MOLD + randint0(6);
243     if (type < SUMMON_MOLD)
244         type = SUMMON_MOLD;
245     else if (type > SUMMON_MIMIC)
246         type = SUMMON_MIMIC;
247
248     auto *floor_ptr = player_ptr->current_floor_ptr;
249     switch (randint1(spell) + randint1(8) + 1) {
250     case 1:
251     case 2:
252     case 3:
253         teleport_player(player_ptr, 10, TELEPORT_PASSIVE);
254         break;
255     case 4:
256     case 5:
257     case 6:
258         teleport_player(player_ptr, 100, TELEPORT_PASSIVE);
259         break;
260     case 7:
261     case 8:
262         teleport_player(player_ptr, 200, TELEPORT_PASSIVE);
263         break;
264     case 9:
265     case 10:
266     case 11:
267         unlite_area(player_ptr, 10, 3);
268         break;
269     case 12:
270     case 13:
271     case 14:
272         lite_area(player_ptr, damroll(2, 3), 2);
273         break;
274     case 15:
275         destroy_doors_touch(player_ptr);
276         break;
277     case 16:
278     case 17:
279         wall_breaker(player_ptr);
280         break;
281     case 18:
282         sleep_monsters_touch(player_ptr);
283         break;
284     case 19:
285     case 20:
286         trap_creation(player_ptr, player_ptr->y, player_ptr->x);
287         break;
288     case 21:
289     case 22:
290         door_creation(player_ptr, player_ptr->y, player_ptr->x);
291         break;
292     case 23:
293     case 24:
294     case 25:
295         aggravate_monsters(player_ptr, 0);
296         break;
297     case 26:
298         earthquake(player_ptr, player_ptr->y, player_ptr->x, 5, 0);
299         break;
300     case 27:
301     case 28:
302         (void)gain_mutation(player_ptr, 0);
303         break;
304     case 29:
305     case 30:
306         apply_disenchant(player_ptr, 1);
307         break;
308     case 31:
309         lose_all_info(player_ptr);
310         break;
311     case 32:
312         fire_ball(player_ptr, AttributeType::CHAOS, 0, spell + 5, 1 + (spell / 10));
313         break;
314     case 33:
315         wall_stone(player_ptr);
316         break;
317     case 34:
318     case 35:
319         for (int counter = 0; counter < 8; counter++) {
320             (void)summon_specific(
321                 player_ptr, 0, player_ptr->y, player_ptr->x, (floor_ptr->dun_level * 3) / 2, i2enum<summon_type>(type), (PM_ALLOW_GROUP | PM_NO_PET));
322         }
323
324         break;
325     case 36:
326     case 37:
327         activate_hi_summon(player_ptr, player_ptr->y, player_ptr->x, false);
328         break;
329     case 38:
330         (void)summon_cyber(player_ptr, -1, player_ptr->y, player_ptr->x);
331         break;
332     default: {
333         int count = 0;
334         (void)activate_ty_curse(player_ptr, false, &count);
335         break;
336     }
337     }
338 }
339
340 /*!
341  * @brief 「ワンダー」のランダムな効果を決定して処理する。
342  * @param player_ptr プレイヤーへの参照ポインタ
343  * @param dir 方向ID
344  * @details
345  * This spell should become more useful (more controlled) as the\n
346  * player gains experience levels.  Thus, add 1/5 of the player's\n
347  * level to the die roll.  This eliminates the worst effects later on,\n
348  * while keeping the results quite random.  It also allows some potent\n
349  * effects only at high level.
350  */
351 void cast_wonder(PlayerType *player_ptr, DIRECTION dir)
352 {
353     PLAYER_LEVEL plev = player_ptr->lev;
354     int die = randint1(100) + plev / 5;
355     int vir = virtue_number(player_ptr, V_CHANCE);
356     if (vir) {
357         if (player_ptr->virtues[vir - 1] > 0) {
358             while (randint1(400) < player_ptr->virtues[vir - 1])
359                 die++;
360         } else {
361             while (randint1(400) < (0 - player_ptr->virtues[vir - 1]))
362                 die--;
363         }
364     }
365
366     if (die < 26) {
367         chg_virtue(player_ptr, V_CHANCE, 1);
368     }
369
370     if (die > 100) {
371         msg_print(_("あなたは力がみなぎるのを感じた!", "You feel a surge of power!"));
372     }
373
374     if (die < 8) {
375         clone_monster(player_ptr, dir);
376         return;
377     }
378
379     if (die < 14) {
380         speed_monster(player_ptr, dir, plev);
381         return;
382     }
383
384     if (die < 26) {
385         heal_monster(player_ptr, dir, damroll(4, 6));
386         return;
387     }
388
389     if (die < 31) {
390         poly_monster(player_ptr, dir, plev);
391         return;
392     }
393
394     if (die < 36) {
395         fire_bolt_or_beam(player_ptr, beam_chance(player_ptr) - 10, AttributeType::MISSILE, dir, damroll(3 + ((plev - 1) / 5), 4));
396         return;
397     }
398
399     if (die < 41) {
400         confuse_monster(player_ptr, dir, plev);
401         return;
402     }
403
404     if (die < 46) {
405         fire_ball(player_ptr, AttributeType::POIS, dir, 20 + (plev / 2), 3);
406         return;
407     }
408
409     if (die < 51) {
410         (void)lite_line(player_ptr, dir, damroll(6, 8));
411         return;
412     }
413
414     if (die < 56) {
415         fire_bolt_or_beam(player_ptr, beam_chance(player_ptr) - 10, AttributeType::ELEC, dir, damroll(3 + ((plev - 5) / 4), 8));
416         return;
417     }
418
419     if (die < 61) {
420         fire_bolt_or_beam(player_ptr, beam_chance(player_ptr) - 10, AttributeType::COLD, dir, damroll(5 + ((plev - 5) / 4), 8));
421         return;
422     }
423
424     if (die < 66) {
425         fire_bolt_or_beam(player_ptr, beam_chance(player_ptr), AttributeType::ACID, dir, damroll(6 + ((plev - 5) / 4), 8));
426         return;
427     }
428
429     if (die < 71) {
430         fire_bolt_or_beam(player_ptr, beam_chance(player_ptr), AttributeType::FIRE, dir, damroll(8 + ((plev - 5) / 4), 8));
431         return;
432     }
433
434     if (die < 76) {
435         hypodynamic_bolt(player_ptr, dir, 75);
436         return;
437     }
438
439     if (die < 81) {
440         fire_ball(player_ptr, AttributeType::ELEC, dir, 30 + plev / 2, 2);
441         return;
442     }
443
444     if (die < 86) {
445         fire_ball(player_ptr, AttributeType::ACID, dir, 40 + plev, 2);
446         return;
447     }
448
449     if (die < 91) {
450         fire_ball(player_ptr, AttributeType::ICE, dir, 70 + plev, 3);
451         return;
452     }
453
454     if (die < 96) {
455         fire_ball(player_ptr, AttributeType::FIRE, dir, 80 + plev, 3);
456         return;
457     }
458
459     if (die < 101) {
460         hypodynamic_bolt(player_ptr, dir, 100 + plev);
461         return;
462     }
463
464     if (die < 104) {
465         earthquake(player_ptr, player_ptr->y, player_ptr->x, 12, 0);
466         return;
467     }
468
469     if (die < 106) {
470         (void)destroy_area(player_ptr, player_ptr->y, player_ptr->x, 13 + randint0(5), false);
471         return;
472     }
473
474     if (die < 108) {
475         symbol_genocide(player_ptr, plev + 50, true);
476         return;
477     }
478
479     if (die < 110) {
480         dispel_monsters(player_ptr, 120);
481         return;
482     }
483
484     dispel_monsters(player_ptr, 150);
485     slow_monsters(player_ptr, plev);
486     sleep_monsters(player_ptr, plev);
487     hp_player(player_ptr, 300);
488 }