OSDN Git Service

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