OSDN Git Service

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