OSDN Git Service

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