OSDN Git Service

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