OSDN Git Service

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