OSDN Git Service

[Refactor] #40482 Separated mutation-techniques.c/h from spells3.c/h
[hengbandforosx/hengbandosx.git] / src / mutation / mutation-processor.c
1 #include "mutation/mutation-processor.h"
2 #include "core/hp-mp-processor.h"
3 #include "grid/grid.h"
4 #include "inventory/inventory-object.h"
5 #include "inventory/inventory-slot-types.h"
6 #include "io/targeting.h"
7 #include "monster-floor/monster-summon.h"
8 #include "monster-floor/place-monster-types.h"
9 #include "monster-race/monster-race.h"
10 #include "monster/monster-status.h"
11 #include "mutation/mutation-flag-types.h"
12 #include "mutation/mutation.h"
13 #include "object-hook/hook-checker.h"
14 #include "object-hook/hook-enchant.h"
15 #include "object/lite-processor.h"
16 #include "player/digestion-processor.h"
17 #include "player/player-damage.h"
18 #include "player/player-move.h"
19 #include "spell-kind/spells-floor.h"
20 #include "spell-kind/spells-launcher.h"
21 #include "spell-kind/spells-lite.h"
22 #include "spell-kind/spells-sight.h"
23 #include "spell-kind/spells-teleport.h"
24 #include "spell-realm/spells-hex.h"
25 #include "spell/spell-types.h"
26 #include "spell/spells-summon.h"
27 #include "spell/spells3.h"
28 #include "status/bad-status-setter.h"
29 #include "status/base-status.h"
30 #include "status/body-improvement.h"
31 #include "status/buff-setter.h"
32 #include "status/form-changer.h"
33 #include "status/shape-changer.h"
34 #include "status/sight-setter.h"
35 #include "store/store-owners.h"
36 #include "store/store-util.h"
37 #include "store/store.h"
38 #include "term/screen-processor.h"
39 #include "view/display-messages.h"
40
41 /*!
42  * @brief 10ゲームターンが進行するごとに突然変異の発動判定を行う処理
43  * / Handle mutation effects once every 10 game turns
44  * @return なし
45  */
46 void process_world_aux_mutation(player_type *creature_ptr)
47 {
48     if (!creature_ptr->muta2 || creature_ptr->phase_out || creature_ptr->wild_mode)
49         return;
50
51     if ((creature_ptr->muta2 & MUT2_BERS_RAGE) && one_in_(3000)) {
52         disturb(creature_ptr, FALSE, TRUE);
53         msg_print(_("ウガァァア!", "RAAAAGHH!"));
54         msg_print(_("激怒の発作に襲われた!", "You feel a fit of rage coming over you!"));
55         (void)set_shero(creature_ptr, 10 + randint1(creature_ptr->lev), FALSE);
56         (void)set_afraid(creature_ptr, 0);
57     }
58
59     if ((creature_ptr->muta2 & MUT2_COWARDICE) && (randint1(3000) == 13)) {
60         if (!creature_ptr->resist_fear) {
61             disturb(creature_ptr, FALSE, TRUE);
62             msg_print(_("とても暗い... とても恐い!", "It's so dark... so scary!"));
63             set_afraid(creature_ptr, creature_ptr->afraid + 13 + randint1(26));
64         }
65     }
66
67     if ((creature_ptr->muta2 & MUT2_RTELEPORT) && (randint1(5000) == 88)) {
68         if (!creature_ptr->resist_nexus && !(creature_ptr->muta1 & MUT1_VTELEPORT) && !creature_ptr->anti_tele) {
69             disturb(creature_ptr, FALSE, TRUE);
70             msg_print(_("あなたの位置は突然ひじょうに不確定になった...", "Your position suddenly seems very uncertain..."));
71             msg_print(NULL);
72             teleport_player(creature_ptr, 40, TELEPORT_PASSIVE);
73         }
74     }
75
76     if ((creature_ptr->muta2 & MUT2_ALCOHOL) && (randint1(6400) == 321)) {
77         if (!creature_ptr->resist_conf && !creature_ptr->resist_chaos) {
78             disturb(creature_ptr, FALSE, TRUE);
79             creature_ptr->redraw |= PR_EXTRA;
80             msg_print(_("いひきがもーろーとひてきたきがふる...ヒック!", "You feel a SSSCHtupor cOmINg over yOu... *HIC*!"));
81         }
82
83         if (!creature_ptr->resist_conf) {
84             (void)set_confused(creature_ptr, creature_ptr->confused + randint0(20) + 15);
85         }
86
87         if (!creature_ptr->resist_chaos) {
88             if (one_in_(20)) {
89                 msg_print(NULL);
90                 if (one_in_(3))
91                     lose_all_info(creature_ptr);
92                 else
93                     wiz_dark(creature_ptr);
94                 (void)teleport_player_aux(creature_ptr, 100, FALSE, TELEPORT_NONMAGICAL | TELEPORT_PASSIVE);
95                 wiz_dark(creature_ptr);
96                 msg_print(_("あなたは見知らぬ場所で目が醒めた...頭が痛い。", "You wake up somewhere with a sore head..."));
97                 msg_print(_("何も覚えていない。どうやってここに来たかも分からない!", "You can't remember a thing or how you got here!"));
98             } else {
99                 if (one_in_(3)) {
100                     msg_print(_("き~れいなちょおちょらとんれいる~", "Thishcischs GooDSChtuff!"));
101                     (void)set_image(creature_ptr, creature_ptr->image + randint0(150) + 150);
102                 }
103             }
104         }
105     }
106
107     if ((creature_ptr->muta2 & MUT2_HALLU) && (randint1(6400) == 42)) {
108         if (!creature_ptr->resist_chaos) {
109             disturb(creature_ptr, FALSE, TRUE);
110             creature_ptr->redraw |= PR_EXTRA;
111             (void)set_image(creature_ptr, creature_ptr->image + randint0(50) + 20);
112         }
113     }
114
115     if ((creature_ptr->muta2 & MUT2_FLATULENT) && (randint1(3000) == 13)) {
116         disturb(creature_ptr, FALSE, TRUE);
117         msg_print(_("ブゥーーッ!おっと。", "BRRAAAP! Oops."));
118         msg_print(NULL);
119         fire_ball(creature_ptr, GF_POIS, 0, creature_ptr->lev, 3);
120     }
121
122     if ((creature_ptr->muta2 & MUT2_PROD_MANA) && !creature_ptr->anti_magic && one_in_(9000)) {
123         int dire = 0;
124         disturb(creature_ptr, FALSE, TRUE);
125         msg_print(_("魔法のエネルギーが突然あなたの中に流れ込んできた!エネルギーを解放しなければならない!",
126             "Magical energy flows through you! You must release it!"));
127
128         flush();
129         msg_print(NULL);
130         (void)get_hack_dir(creature_ptr, &dire);
131         fire_ball(creature_ptr, GF_MANA, dire, creature_ptr->lev * 2, 3);
132     }
133
134     if ((creature_ptr->muta2 & MUT2_ATT_DEMON) && !creature_ptr->anti_magic && (randint1(6666) == 666)) {
135         bool pet = one_in_(6);
136         BIT_FLAGS mode = PM_ALLOW_GROUP;
137
138         if (pet)
139             mode |= PM_FORCE_PET;
140         else
141             mode |= (PM_ALLOW_UNIQUE | PM_NO_PET);
142
143         if (summon_specific(creature_ptr, (pet ? -1 : 0), creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_DEMON, mode)) {
144             msg_print(_("あなたはデーモンを引き寄せた!", "You have attracted a demon!"));
145             disturb(creature_ptr, FALSE, TRUE);
146         }
147     }
148
149     if ((creature_ptr->muta2 & MUT2_SPEED_FLUX) && one_in_(6000)) {
150         disturb(creature_ptr, FALSE, TRUE);
151         if (one_in_(2)) {
152             msg_print(_("精力的でなくなった気がする。", "You feel less energetic."));
153
154             if (creature_ptr->fast > 0) {
155                 set_fast(creature_ptr, 0, TRUE);
156             } else {
157                 set_slow(creature_ptr, randint1(30) + 10, FALSE);
158             }
159         } else {
160             msg_print(_("精力的になった気がする。", "You feel more energetic."));
161
162             if (creature_ptr->slow > 0) {
163                 set_slow(creature_ptr, 0, TRUE);
164             } else {
165                 set_fast(creature_ptr, randint1(30) + 10, FALSE);
166             }
167         }
168         msg_print(NULL);
169     }
170     if ((creature_ptr->muta2 & MUT2_BANISH_ALL) && one_in_(9000)) {
171         disturb(creature_ptr, FALSE, TRUE);
172         msg_print(_("突然ほとんど孤独になった気がする。", "You suddenly feel almost lonely."));
173
174         banish_monsters(creature_ptr, 100);
175         if (!creature_ptr->current_floor_ptr->dun_level && creature_ptr->town_num) {
176             int n;
177             do {
178                 n = randint0(MAX_STORES);
179             } while ((n == STORE_HOME) || (n == STORE_MUSEUM));
180
181             msg_print(_("店の主人が丘に向かって走っている!", "You see one of the shopkeepers running for the hills!"));
182             store_shuffle(creature_ptr, n);
183         }
184         msg_print(NULL);
185     }
186
187     if ((creature_ptr->muta2 & MUT2_EAT_LIGHT) && one_in_(3000)) {
188         object_type *o_ptr;
189
190         msg_print(_("影につつまれた。", "A shadow passes over you."));
191         msg_print(NULL);
192
193         if ((creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) {
194             hp_player(creature_ptr, 10);
195         }
196
197         o_ptr = &creature_ptr->inventory_list[INVEN_LITE];
198
199         if (o_ptr->tval == TV_LITE) {
200             if (!object_is_fixed_artifact(o_ptr) && (o_ptr->xtra4 > 0)) {
201                 hp_player(creature_ptr, o_ptr->xtra4 / 20);
202                 o_ptr->xtra4 /= 2;
203                 msg_print(_("光源からエネルギーを吸収した!", "You absorb energy from your light!"));
204                 notice_lite_change(creature_ptr, o_ptr);
205             }
206         }
207
208         /*
209          * Unlite the area (radius 10) around player and
210          * do 50 points damage to every affected monster
211          */
212         unlite_area(creature_ptr, 50, 10);
213     }
214
215     if ((creature_ptr->muta2 & MUT2_ATT_ANIMAL) && !creature_ptr->anti_magic && one_in_(7000)) {
216         bool pet = one_in_(3);
217         BIT_FLAGS mode = PM_ALLOW_GROUP;
218
219         if (pet)
220             mode |= PM_FORCE_PET;
221         else
222             mode |= (PM_ALLOW_UNIQUE | PM_NO_PET);
223
224         if (summon_specific(creature_ptr, (pet ? -1 : 0), creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_ANIMAL, mode)) {
225             msg_print(_("動物を引き寄せた!", "You have attracted an animal!"));
226             disturb(creature_ptr, FALSE, TRUE);
227         }
228     }
229
230     if ((creature_ptr->muta2 & MUT2_RAW_CHAOS) && !creature_ptr->anti_magic && one_in_(8000)) {
231         disturb(creature_ptr, FALSE, TRUE);
232         msg_print(_("周りの空間が歪んでいる気がする!", "You feel the world warping around you!"));
233
234         msg_print(NULL);
235         fire_ball(creature_ptr, GF_CHAOS, 0, creature_ptr->lev, 8);
236     }
237
238     if ((creature_ptr->muta2 & MUT2_NORMALITY) && one_in_(5000)) {
239         if (!lose_mutation(creature_ptr, 0))
240             msg_print(_("奇妙なくらい普通になった気がする。", "You feel oddly normal."));
241     }
242
243     if ((creature_ptr->muta2 & MUT2_WRAITH) && !creature_ptr->anti_magic && one_in_(3000)) {
244         disturb(creature_ptr, FALSE, TRUE);
245         msg_print(_("非物質化した!", "You feel insubstantial!"));
246
247         msg_print(NULL);
248         set_wraith_form(creature_ptr, randint1(creature_ptr->lev / 2) + (creature_ptr->lev / 2), FALSE);
249     }
250
251     if ((creature_ptr->muta2 & MUT2_POLY_WOUND) && one_in_(3000)) {
252         do_poly_wounds(creature_ptr);
253     }
254
255     if ((creature_ptr->muta2 & MUT2_WASTING) && one_in_(3000)) {
256         int which_stat = randint0(A_MAX);
257         int sustained = FALSE;
258
259         switch (which_stat) {
260         case A_STR:
261             if (creature_ptr->sustain_str)
262                 sustained = TRUE;
263             break;
264         case A_INT:
265             if (creature_ptr->sustain_int)
266                 sustained = TRUE;
267             break;
268         case A_WIS:
269             if (creature_ptr->sustain_wis)
270                 sustained = TRUE;
271             break;
272         case A_DEX:
273             if (creature_ptr->sustain_dex)
274                 sustained = TRUE;
275             break;
276         case A_CON:
277             if (creature_ptr->sustain_con)
278                 sustained = TRUE;
279             break;
280         case A_CHR:
281             if (creature_ptr->sustain_chr)
282                 sustained = TRUE;
283             break;
284         default:
285             msg_print(_("不正な状態!", "Invalid stat chosen!"));
286             sustained = TRUE;
287         }
288
289         if (!sustained) {
290             disturb(creature_ptr, FALSE, TRUE);
291             msg_print(_("自分が衰弱していくのが分かる!", "You can feel yourself wasting away!"));
292             msg_print(NULL);
293             (void)dec_stat(creature_ptr, which_stat, randint1(6) + 6, one_in_(3));
294         }
295     }
296
297     if ((creature_ptr->muta2 & MUT2_ATT_DRAGON) && !creature_ptr->anti_magic && one_in_(3000)) {
298         bool pet = one_in_(5);
299         BIT_FLAGS mode = PM_ALLOW_GROUP;
300
301         if (pet)
302             mode |= PM_FORCE_PET;
303         else
304             mode |= (PM_ALLOW_UNIQUE | PM_NO_PET);
305
306         if (summon_specific(creature_ptr, (pet ? -1 : 0), creature_ptr->y, creature_ptr->x, creature_ptr->current_floor_ptr->dun_level, SUMMON_DRAGON, mode)) {
307             msg_print(_("ドラゴンを引き寄せた!", "You have attracted a dragon!"));
308             disturb(creature_ptr, FALSE, TRUE);
309         }
310     }
311
312     if ((creature_ptr->muta2 & MUT2_WEIRD_MIND) && !creature_ptr->anti_magic && one_in_(3000)) {
313         if (creature_ptr->tim_esp > 0) {
314             msg_print(_("精神にもやがかかった!", "Your mind feels cloudy!"));
315             set_tim_esp(creature_ptr, 0, TRUE);
316         } else {
317             msg_print(_("精神が広がった!", "Your mind expands!"));
318             set_tim_esp(creature_ptr, creature_ptr->lev, FALSE);
319         }
320     }
321
322     if ((creature_ptr->muta2 & MUT2_NAUSEA) && !creature_ptr->slow_digest && one_in_(9000)) {
323         disturb(creature_ptr, FALSE, TRUE);
324         msg_print(_("胃が痙攣し、食事を失った!", "Your stomach roils, and you lose your lunch!"));
325         msg_print(NULL);
326         set_food(creature_ptr, PY_FOOD_WEAK);
327         if (music_singing_any(creature_ptr))
328             stop_singing(creature_ptr);
329         if (hex_spelling_any(creature_ptr))
330             stop_hex_spell_all(creature_ptr);
331     }
332
333     if ((creature_ptr->muta2 & MUT2_WALK_SHAD) && !creature_ptr->anti_magic && one_in_(12000) && !creature_ptr->current_floor_ptr->inside_arena) {
334         reserve_alter_reality(creature_ptr);
335     }
336
337     if ((creature_ptr->muta2 & MUT2_WARNING) && one_in_(1000)) {
338         int danger_amount = 0;
339         for (MONSTER_IDX monster = 0; monster < creature_ptr->current_floor_ptr->m_max; monster++) {
340             monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[monster];
341             monster_race *r_ptr = &r_info[m_ptr->r_idx];
342             if (!monster_is_valid(m_ptr))
343                 continue;
344
345             if (r_ptr->level >= creature_ptr->lev) {
346                 danger_amount += r_ptr->level - creature_ptr->lev + 1;
347             }
348         }
349
350         if (danger_amount > 100)
351             msg_print(_("非常に恐ろしい気がする!", "You feel utterly terrified!"));
352         else if (danger_amount > 50)
353             msg_print(_("恐ろしい気がする!", "You feel terrified!"));
354         else if (danger_amount > 20)
355             msg_print(_("非常に心配な気がする!", "You feel very worried!"));
356         else if (danger_amount > 10)
357             msg_print(_("心配な気がする!", "You feel paranoid!"));
358         else if (danger_amount > 5)
359             msg_print(_("ほとんど安全な気がする。", "You feel almost safe."));
360         else
361             msg_print(_("寂しい気がする。", "You feel lonely."));
362     }
363
364     if ((creature_ptr->muta2 & MUT2_INVULN) && !creature_ptr->anti_magic && one_in_(5000)) {
365         disturb(creature_ptr, FALSE, TRUE);
366         msg_print(_("無敵な気がする!", "You feel invincible!"));
367         msg_print(NULL);
368         (void)set_invuln(creature_ptr, randint1(8) + 8, FALSE);
369     }
370
371     if ((creature_ptr->muta2 & MUT2_SP_TO_HP) && one_in_(2000)) {
372         MANA_POINT wounds = (MANA_POINT)(creature_ptr->mhp - creature_ptr->chp);
373
374         if (wounds > 0) {
375             HIT_POINT healing = creature_ptr->csp;
376             if (healing > wounds)
377                 healing = wounds;
378
379             hp_player(creature_ptr, healing);
380             creature_ptr->csp -= healing;
381             creature_ptr->redraw |= (PR_HP | PR_MANA);
382         }
383     }
384
385     if ((creature_ptr->muta2 & MUT2_HP_TO_SP) && !creature_ptr->anti_magic && one_in_(4000)) {
386         HIT_POINT wounds = (HIT_POINT)(creature_ptr->msp - creature_ptr->csp);
387
388         if (wounds > 0) {
389             HIT_POINT healing = creature_ptr->chp;
390             if (healing > wounds)
391                 healing = wounds;
392
393             creature_ptr->csp += healing;
394             creature_ptr->redraw |= (PR_HP | PR_MANA);
395             take_hit(creature_ptr, DAMAGE_LOSELIFE, healing, _("頭に昇った血", "blood rushing to the head"), -1);
396         }
397     }
398
399     if ((creature_ptr->muta2 & MUT2_DISARM) && one_in_(10000)) {
400         disturb(creature_ptr, FALSE, TRUE);
401         msg_print(_("足がもつれて転んだ!", "You trip over your own feet!"));
402         take_hit(creature_ptr, DAMAGE_NOESCAPE, randint1(creature_ptr->wt / 6), _("転倒", "tripping"), -1);
403         drop_weapons(creature_ptr);
404     }
405 }
406
407 bool drop_weapons(player_type *creature_ptr)
408 {
409     INVENTORY_IDX slot = 0;
410     object_type *o_ptr = NULL;
411
412     if (creature_ptr->wild_mode)
413         return FALSE;
414
415     msg_print(NULL);
416     if (has_melee_weapon(creature_ptr, INVEN_RARM)) {
417         slot = INVEN_RARM;
418         o_ptr = &creature_ptr->inventory_list[INVEN_RARM];
419
420         if (has_melee_weapon(creature_ptr, INVEN_LARM) && one_in_(2)) {
421             o_ptr = &creature_ptr->inventory_list[INVEN_LARM];
422             slot = INVEN_LARM;
423         }
424     } else if (has_melee_weapon(creature_ptr, INVEN_LARM)) {
425         o_ptr = &creature_ptr->inventory_list[INVEN_LARM];
426         slot = INVEN_LARM;
427     }
428
429     if (slot && !object_is_cursed(o_ptr)) {
430         msg_print(_("武器を落としてしまった!", "You drop your weapon!"));
431         drop_from_inventory(creature_ptr, slot, 1);
432         return TRUE;
433     }
434
435     return FALSE;
436 }