OSDN Git Service

[Refactor] #37353 potion_smash_effect() to object-broken.c.
[hengband/hengband.git] / src / cmd-quaff.c
1 /*!
2  * @file cmd-quaff.c
3  * @brief プレイヤーの飲むコマンド実装
4  * @date 2018/09/07
5  * @details
6  * cmd6.cより分離。
7  */
8
9 #include "angband.h"
10 #include "selfinfo.h"
11 #include "object-hook.h"
12 #include "mutation.h"
13 #include "avatar.h"
14 #include "spells-status.h"
15 #include "realm-hex.h"
16 #include "spells-floor.h"
17 #include "object-broken.h"
18
19 /*!
20  * @brief 薬を飲むコマンドのサブルーチン /
21  * Quaff a potion (from the pack or the floor)
22  * @param item 飲む薬オブジェクトの所持品ID
23  * @return なし
24  */
25 void do_cmd_quaff_potion_aux(INVENTORY_IDX item)
26 {
27         bool ident;
28         DEPTH lev;
29         object_type *o_ptr;
30         object_type forge;
31         object_type *q_ptr;
32
33
34         if (p_ptr->timewalk)
35         {
36                 if (flush_failure) flush();
37                 msg_print(_("瓶から水が流れ出てこない!", "The potion doesn't flow out from a bottle."));
38
39                 sound(SOUND_FAIL);
40                 return;
41         }
42
43         if (music_singing_any()) stop_singing(p_ptr);
44         if (hex_spelling_any())
45         {
46                 if (!hex_spelling(HEX_INHAIL)) stop_hex_spell_all();
47         }
48
49         /* Get the item (in the pack) */
50         if (item >= 0)
51         {
52                 o_ptr = &inventory[item];
53         }
54
55         /* Get the item (on the floor) */
56         else
57         {
58                 o_ptr = &current_floor_ptr->o_list[0 - item];
59         }
60         q_ptr = &forge;
61
62         /* Obtain a local object */
63         object_copy(q_ptr, o_ptr);
64
65         /* Single object */
66         q_ptr->number = 1;
67
68         /* Reduce and describe inventory */
69         if (item >= 0)
70         {
71                 inven_item_increase(item, -1);
72                 inven_item_describe(item);
73                 inven_item_optimize(item);
74         }
75
76         /* Reduce and describe floor item */
77         else
78         {
79                 floor_item_increase(0 - item, -1);
80                 floor_item_describe(0 - item);
81                 floor_item_optimize(0 - item);
82         }
83
84         sound(SOUND_QUAFF);
85
86
87         /* Not identified yet */
88         ident = FALSE;
89
90         /* Object level */
91         lev = k_info[q_ptr->k_idx].level;
92
93         /* Analyze the potion */
94         if (q_ptr->tval == TV_POTION)
95         {
96                 switch (q_ptr->sval)
97                 {
98                         /* 飲みごたえをオリジナルより細かく表現 */
99                 case SV_POTION_WATER:
100                         msg_print(_("口の中がさっぱりした。", ""));
101                         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
102                         ident = TRUE;
103                         break;
104
105                 case SV_POTION_APPLE_JUICE:
106                         msg_print(_("甘くてサッパリとしていて、とてもおいしい。", ""));
107                         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
108                         ident = TRUE;
109                         break;
110
111                 case SV_POTION_SLIME_MOLD:
112                         msg_print(_("なんとも不気味な味だ。", ""));
113                         msg_print(_("のどの渇きが少しおさまった。", "You feel less thirsty."));
114                         ident = TRUE;
115                         break;
116
117                 case SV_POTION_SLOWNESS:
118                         if (set_slow(randint1(25) + 15, FALSE)) ident = TRUE;
119                         break;
120
121                 case SV_POTION_SALT_WATER:
122                         msg_print(_("うぇ!思わず吐いてしまった。", "The potion makes you vomit!"));
123
124                         if (!(prace_is_(RACE_GOLEM) ||
125                               prace_is_(RACE_ZOMBIE) ||
126                               prace_is_(RACE_DEMON) ||
127                               prace_is_(RACE_ANDROID) ||
128                               prace_is_(RACE_SPECTRE) ||
129                               (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)))
130                         {
131                                 /* Only living creatures get thirsty */
132                                 (void)set_food(PY_FOOD_STARVE - 1);
133                         }
134
135                         (void)set_poisoned(0);
136                         (void)set_paralyzed(p_ptr->paralyzed + 4);
137                         ident = TRUE;
138                         break;
139
140                 case SV_POTION_POISON:
141                         if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))
142                         {
143                                 if (set_poisoned(p_ptr->poisoned + randint0(15) + 10))
144                                 {
145                                         ident = TRUE;
146                                 }
147                         }
148                         break;
149
150                 case SV_POTION_BLINDNESS:
151                         if (!p_ptr->resist_blind)
152                         {
153                                 if (set_blind(p_ptr->blind + randint0(100) + 100))
154                                 {
155                                         ident = TRUE;
156                                 }
157                         }
158                         break;
159
160                 case SV_POTION_BOOZE:
161                         ident = booze(p_ptr);
162                         break;
163
164                 case SV_POTION_SLEEP:
165                         if (!p_ptr->free_act)
166                         {
167                                 msg_print(_("あなたは眠ってしまった。", "You fall asleep."));
168
169                                 if (ironman_nightmare)
170                                 {
171                                         msg_print(_("恐ろしい光景が頭に浮かんできた。", "A horrible vision enters your mind."));
172
173                                         /* Have some nightmares */
174                                         sanity_blast(NULL, FALSE);
175                                 }
176                                 if (set_paralyzed(p_ptr->paralyzed + randint0(4) + 4))
177                                 {
178                                         ident = TRUE;
179                                 }
180                         }
181                         break;
182
183                 case SV_POTION_LOSE_MEMORIES:
184                         if (!p_ptr->hold_exp && (p_ptr->exp > 0))
185                         {
186                                 msg_print(_("過去の記憶が薄れていく気がする。", "You feel your memories fade."));
187                                 chg_virtue(V_KNOWLEDGE, -5);
188
189                                 lose_exp(p_ptr->exp / 4);
190                                 ident = TRUE;
191                         }
192                         break;
193
194                 case SV_POTION_RUINATION:
195                         msg_print(_("身も心も弱ってきて、精気が抜けていくようだ。", "Your nerves and muscles feel weak and lifeless!"));
196                         take_hit(DAMAGE_LOSELIFE, damroll(10, 10), _("破滅の薬", "a potion of Ruination"), -1);
197
198                         (void)dec_stat(A_DEX, 25, TRUE);
199                         (void)dec_stat(A_WIS, 25, TRUE);
200                         (void)dec_stat(A_CON, 25, TRUE);
201                         (void)dec_stat(A_STR, 25, TRUE);
202                         (void)dec_stat(A_CHR, 25, TRUE);
203                         (void)dec_stat(A_INT, 25, TRUE);
204                         ident = TRUE;
205                         break;
206
207                 case SV_POTION_DEC_STR:
208                         if (do_dec_stat(A_STR)) ident = TRUE;
209                         break;
210
211                 case SV_POTION_DEC_INT:
212                         if (do_dec_stat(A_INT)) ident = TRUE;
213                         break;
214
215                 case SV_POTION_DEC_WIS:
216                         if (do_dec_stat(A_WIS)) ident = TRUE;
217                         break;
218
219                 case SV_POTION_DEC_DEX:
220                         if (do_dec_stat(A_DEX)) ident = TRUE;
221                         break;
222
223                 case SV_POTION_DEC_CON:
224                         if (do_dec_stat(A_CON)) ident = TRUE;
225                         break;
226
227                 case SV_POTION_DEC_CHR:
228                         if (do_dec_stat(A_CHR)) ident = TRUE;
229                         break;
230
231                 case SV_POTION_DETONATIONS:
232                         ident = detonation(p_ptr);
233                         break;
234
235                 case SV_POTION_DEATH:
236                         chg_virtue(V_VITALITY, -1);
237                         chg_virtue(V_UNLIFE, 5);
238                         msg_print(_("死の予感が体中を駆けめぐった。", "A feeling of Death flows through your body."));
239                         take_hit(DAMAGE_LOSELIFE, 5000, _("死の薬", "a potion of Death"), -1);
240                         ident = TRUE;
241                         break;
242
243                 case SV_POTION_INFRAVISION:
244                         if (set_tim_infra(p_ptr->tim_infra + 100 + randint1(100), FALSE))
245                         {
246                                 ident = TRUE;
247                         }
248                         break;
249
250                 case SV_POTION_DETECT_INVIS:
251                         if (set_tim_invis(p_ptr->tim_invis + 12 + randint1(12), FALSE))
252                         {
253                                 ident = TRUE;
254                         }
255                         break;
256
257                 case SV_POTION_SLOW_POISON:
258                         if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE;
259                         break;
260
261                 case SV_POTION_CURE_POISON:
262                         if (set_poisoned(0)) ident = TRUE;
263                         break;
264
265                 case SV_POTION_BOLDNESS:
266                         if (set_afraid(0)) ident = TRUE;
267                         break;
268
269                 case SV_POTION_SPEED:
270                         if (!p_ptr->fast)
271                         {
272                                 if (set_fast(randint1(25) + 15, FALSE)) ident = TRUE;
273                         }
274                         else
275                         {
276                                 (void)set_fast(p_ptr->fast + 5, FALSE);
277                         }
278                         break;
279
280                 case SV_POTION_RESIST_HEAT:
281                         if (set_oppose_fire(p_ptr->oppose_fire + randint1(10) + 10, FALSE))
282                         {
283                                 ident = TRUE;
284                         }
285                         break;
286
287                 case SV_POTION_RESIST_COLD:
288                         if (set_oppose_cold(p_ptr->oppose_cold + randint1(10) + 10, FALSE))
289                         {
290                                 ident = TRUE;
291                         }
292                         break;
293
294                 case SV_POTION_HEROISM:
295                         ident = heroism(25);
296                         break;
297
298                 case SV_POTION_BESERK_STRENGTH:
299                         ident = berserk(randint1(25) + 25);
300                         break;
301
302                 case SV_POTION_CURE_LIGHT:
303                         ident = cure_light_wounds(2, 8);
304                         break;
305
306                 case SV_POTION_CURE_SERIOUS:
307                         ident = cure_serious_wounds(4, 8);
308                         break;
309
310                 case SV_POTION_CURE_CRITICAL:
311                         ident = cure_critical_wounds(damroll(6, 8));
312                         break;
313
314                 case SV_POTION_HEALING:
315                         ident = cure_critical_wounds(300);
316                         break;
317
318                 case SV_POTION_STAR_HEALING:
319                         ident = cure_critical_wounds(1200);
320                         break;
321
322                 case SV_POTION_LIFE:
323                         ident = life_stream(TRUE, TRUE);
324                         break;
325
326                 case SV_POTION_RESTORE_MANA:
327                         ident = restore_mana(TRUE);
328                         break;
329
330                 case SV_POTION_RESTORE_EXP:
331                         if (restore_level()) ident = TRUE;
332                         break;
333
334                 case SV_POTION_RES_STR:
335                         if (do_res_stat(A_STR)) ident = TRUE;
336                         break;
337
338                 case SV_POTION_RES_INT:
339                         if (do_res_stat(A_INT)) ident = TRUE;
340                         break;
341
342                 case SV_POTION_RES_WIS:
343                         if (do_res_stat(A_WIS)) ident = TRUE;
344                         break;
345
346                 case SV_POTION_RES_DEX:
347                         if (do_res_stat(A_DEX)) ident = TRUE;
348                         break;
349
350                 case SV_POTION_RES_CON:
351                         if (do_res_stat(A_CON)) ident = TRUE;
352                         break;
353
354                 case SV_POTION_RES_CHR:
355                         if (do_res_stat(A_CHR)) ident = TRUE;
356                         break;
357
358                 case SV_POTION_INC_STR:
359                         if (do_inc_stat(A_STR)) ident = TRUE;
360                         break;
361
362                 case SV_POTION_INC_INT:
363                         if (do_inc_stat(A_INT)) ident = TRUE;
364                         break;
365
366                 case SV_POTION_INC_WIS:
367                         if (do_inc_stat(A_WIS)) ident = TRUE;
368                         break;
369
370                 case SV_POTION_INC_DEX:
371                         if (do_inc_stat(A_DEX)) ident = TRUE;
372                         break;
373
374                 case SV_POTION_INC_CON:
375                         if (do_inc_stat(A_CON)) ident = TRUE;
376                         break;
377
378                 case SV_POTION_INC_CHR:
379                         if (do_inc_stat(A_CHR)) ident = TRUE;
380                         break;
381
382                 case SV_POTION_AUGMENTATION:
383                         if (do_inc_stat(A_STR)) ident = TRUE;
384                         if (do_inc_stat(A_INT)) ident = TRUE;
385                         if (do_inc_stat(A_WIS)) ident = TRUE;
386                         if (do_inc_stat(A_DEX)) ident = TRUE;
387                         if (do_inc_stat(A_CON)) ident = TRUE;
388                         if (do_inc_stat(A_CHR)) ident = TRUE;
389                         break;
390
391                 case SV_POTION_ENLIGHTENMENT:
392                         msg_print(_("自分の置かれている状況が脳裏に浮かんできた...", "An image of your surroundings forms in your mind..."));
393                         chg_virtue(V_KNOWLEDGE, 1);
394                         chg_virtue(V_ENLIGHTEN, 1);
395                         wiz_lite(FALSE);
396                         ident = TRUE;
397                         break;
398
399                 case SV_POTION_STAR_ENLIGHTENMENT:
400                         msg_print(_("更なる啓蒙を感じた...", "You begin to feel more enlightened..."));
401                         chg_virtue(V_KNOWLEDGE, 1);
402                         chg_virtue(V_ENLIGHTEN, 2);
403                         msg_print(NULL);
404                         wiz_lite(FALSE);
405                         (void)do_inc_stat(A_INT);
406                         (void)do_inc_stat(A_WIS);
407                         (void)detect_traps(DETECT_RAD_DEFAULT, TRUE);
408                         (void)detect_doors(DETECT_RAD_DEFAULT);
409                         (void)detect_stairs(DETECT_RAD_DEFAULT);
410                         (void)detect_treasure(DETECT_RAD_DEFAULT);
411                         (void)detect_objects_gold(DETECT_RAD_DEFAULT);
412                         (void)detect_objects_normal(DETECT_RAD_DEFAULT);
413                         identify_pack();
414                         self_knowledge();
415                         ident = TRUE;
416                         break;
417
418                 case SV_POTION_SELF_KNOWLEDGE:
419                         msg_print(_("自分自身のことが少しは分かった気がする...", "You begin to know yourself a little better..."));
420                         msg_print(NULL);
421                         self_knowledge();
422                         ident = TRUE;
423                         break;
424
425                 case SV_POTION_EXPERIENCE:
426                         if (p_ptr->prace == RACE_ANDROID) break;
427                         chg_virtue(V_ENLIGHTEN, 1);
428                         if (p_ptr->exp < PY_MAX_EXP)
429                         {
430                                 EXP ee = (p_ptr->exp / 2) + 10;
431                                 if (ee > 100000L) ee = 100000L;
432                                 msg_print(_("更に経験を積んだような気がする。", "You feel more experienced."));
433                                 gain_exp(ee);
434                                 ident = TRUE;
435                         }
436                         break;
437
438                 case SV_POTION_RESISTANCE:
439                         (void)set_oppose_acid(p_ptr->oppose_acid + randint1(20) + 20, FALSE);
440                         (void)set_oppose_elec(p_ptr->oppose_elec + randint1(20) + 20, FALSE);
441                         (void)set_oppose_fire(p_ptr->oppose_fire + randint1(20) + 20, FALSE);
442                         (void)set_oppose_cold(p_ptr->oppose_cold + randint1(20) + 20, FALSE);
443                         (void)set_oppose_pois(p_ptr->oppose_pois + randint1(20) + 20, FALSE);
444                         ident = TRUE;
445                         break;
446
447                 case SV_POTION_CURING:
448                         if (true_healing(50)) ident = TRUE;
449                         break;
450
451                 case SV_POTION_INVULNERABILITY:
452                         (void)set_invuln(p_ptr->invuln + randint1(4) + 4, FALSE);
453                         ident = TRUE;
454                         break;
455
456                 case SV_POTION_NEW_LIFE:
457                         roll_hitdice(p_ptr, 0L);
458                         get_max_stats();
459                         p_ptr->update |= PU_BONUS;
460                         lose_all_mutations();
461                         ident = TRUE;
462                         break;
463
464                 case SV_POTION_NEO_TSUYOSHI:
465                         (void)set_image(0);
466                         (void)set_tsuyoshi(p_ptr->tsuyoshi + randint1(100) + 100, FALSE);
467                         ident = TRUE;
468                         break;
469
470                 case SV_POTION_TSUYOSHI:
471                         msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
472                         msg_print(NULL);
473                         p_ptr->tsuyoshi = 1;
474                         (void)set_tsuyoshi(0, TRUE);
475                         if (!p_ptr->resist_chaos)
476                         {
477                                 (void)set_image(50 + randint1(50));
478                         }
479                         ident = TRUE;
480                         break;
481                 
482                 case SV_POTION_POLYMORPH:
483                         if ((p_ptr->muta1 || p_ptr->muta2 || p_ptr->muta3) && one_in_(23))
484                         {
485                                 lose_all_mutations();
486                         }
487                         else
488                         {
489                                 do
490                                 {
491                                         if (one_in_(2))
492                                         {
493                                                 if(gain_mutation(p_ptr, 0)) ident = TRUE;
494                                         }
495                                         else if (lose_mutation(0)) ident = TRUE;
496                                 } while(!ident || one_in_(2));
497                         }
498                         break;
499                 }
500         }
501
502         if (prace_is_(RACE_SKELETON))
503         {
504                 msg_print(_("液体の一部はあなたのアゴを素通りして落ちた!", "Some of the fluid falls through your jaws!"));
505                 (void)potion_smash_effect(0, p_ptr->y, p_ptr->x, q_ptr->k_idx);
506         }
507         p_ptr->update |= (PU_COMBINE | PU_REORDER);
508
509         if (!(object_is_aware(q_ptr)))
510         {
511                 chg_virtue(V_PATIENCE, -1);
512                 chg_virtue(V_CHANCE, 1);
513                 chg_virtue(V_KNOWLEDGE, -1);
514         }
515
516         /* The item has been tried */
517         object_tried(q_ptr);
518
519         /* An identification was made */
520         if (ident && !object_is_aware(q_ptr))
521         {
522                 object_aware(q_ptr);
523                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
524         }
525
526         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
527
528         /* Potions can feed the player */
529         switch (p_ptr->mimic_form)
530         {
531         case MIMIC_NONE:
532                 switch (p_ptr->prace)
533                 {
534                         case RACE_VAMPIRE:
535                                 (void)set_food(p_ptr->food + (q_ptr->pval / 10));
536                                 break;
537                         case RACE_SKELETON:
538                                 /* Do nothing */
539                                 break;
540                         case RACE_GOLEM:
541                         case RACE_ZOMBIE:
542                         case RACE_DEMON:
543                         case RACE_SPECTRE:
544                                 set_food(p_ptr->food + ((q_ptr->pval) / 20));
545                                 break;
546                         case RACE_ANDROID:
547                                 if (q_ptr->tval == TV_FLASK)
548                                 {
549                                         msg_print(_("オイルを補給した。", "You replenish yourself with the oil."));
550                                         set_food(p_ptr->food + 5000);
551                                 }
552                                 else
553                                 {
554                                         set_food(p_ptr->food + ((q_ptr->pval) / 20));
555                                 }
556                                 break;
557                         case RACE_ENT:
558                                 msg_print(_("水分を取り込んだ。", "You are moistened."));
559                                 set_food(MIN(p_ptr->food + q_ptr->pval + MAX(0, q_ptr->pval * 10) + 2000, PY_FOOD_MAX - 1));
560                                 break;
561                         default:
562                                 (void)set_food(p_ptr->food + q_ptr->pval);
563                                 break;
564                 }
565                 break;
566         case MIMIC_DEMON:
567         case MIMIC_DEMON_LORD:
568                 set_food(p_ptr->food + ((q_ptr->pval) / 20));
569                 break;
570         case MIMIC_VAMPIRE:
571                 (void)set_food(p_ptr->food + (q_ptr->pval / 10));
572                 break;
573         default:
574                 (void)set_food(p_ptr->food + q_ptr->pval);
575                 break;
576         }
577 }
578
579
580
581 /*!
582  * @brief 薬を飲むコマンドのメインルーチン /
583  * Quaff some potion (from the pack or floor)
584  * @return なし
585  */
586 void do_cmd_quaff_potion(void)
587 {
588         OBJECT_IDX item;
589         concptr q, s;
590
591         if (p_ptr->wild_mode)
592         {
593                 return;
594         }
595
596         if (cmd_limit_arena(p_ptr)) return;
597
598         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
599         {
600                 set_action(ACTION_NONE);
601         }
602
603         /* Restrict choices to potions */
604         item_tester_hook = item_tester_hook_quaff;
605
606         q = _("どの薬を飲みますか? ", "Quaff which potion? ");
607         s = _("飲める薬がない。", "You have no potions to quaff.");
608
609         if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
610
611         /* Quaff the potion */
612         do_cmd_quaff_potion_aux(item);
613 }