OSDN Git Service

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