OSDN Git Service

0a8c53e1962e727ebae6c1458e09fdd6cf9a1f57
[hengband/hengband.git] / src / cmd-eat.c
1 /*!
2  * @file cmd-eat.c
3  * @brief プレイヤーの食べるコマンド実装
4  * @date 2018/09/07
5  * @details
6  * cmd6.cより分離。
7  */
8
9
10 #include "angband.h"
11 #include "util.h"
12
13 #include "object-flavor.h"
14 #include "object-hook.h"
15 #include "avatar.h"
16 #include "spells-status.h"
17 #include "realm-hex.h"
18 #include "player-status.h"
19 #include "player-effects.h"
20 #include "player-damage.h"
21 #include "player-race.h"
22 #include "player-class.h"
23 #include "floor.h"
24 #include "objectkind.h"
25 #include "realm.h"
26 #include "realm-song.h"
27 #include "view-mainwindow.h"
28
29 /*!
30  * @brief 食料を食べるコマンドのサブルーチン
31  * @param item 食べるオブジェクトの所持品ID
32  * @return なし
33  */
34 void exe_eat_food(INVENTORY_IDX item)
35 {
36         int ident, lev;
37         object_type *o_ptr;
38
39         if (music_singing_any()) stop_singing(p_ptr);
40         if (hex_spelling_any()) stop_hex_spell_all();
41
42         /* Get the item (in the pack) */
43         if (item >= 0)
44         {
45                 o_ptr = &p_ptr->inventory_list[item];
46         }
47
48         /* Get the item (on the floor) */
49         else
50         {
51                 o_ptr = &current_floor_ptr->o_list[0 - item];
52         }
53
54         sound(SOUND_EAT);
55
56         take_turn(p_ptr, 100);
57
58         /* Identity not known yet */
59         ident = FALSE;
60
61         /* Object level */
62         lev = k_info[o_ptr->k_idx].level;
63
64         if (o_ptr->tval == TV_FOOD)
65         {
66                 /* Analyze the food */
67                 switch (o_ptr->sval)
68                 {
69                 case SV_FOOD_POISON:
70                 {
71                         if (!(p_ptr->resist_pois || IS_OPPOSE_POIS()))
72                         {
73                                 if (set_poisoned(p_ptr, p_ptr->poisoned + randint0(10) + 10))
74                                 {
75                                         ident = TRUE;
76                                 }
77                         }
78                         break;
79                 }
80
81                 case SV_FOOD_BLINDNESS:
82                 {
83                         if (!p_ptr->resist_blind)
84                         {
85                                 if (set_blind(p_ptr, p_ptr->blind + randint0(200) + 200))
86                                 {
87                                         ident = TRUE;
88                                 }
89                         }
90                         break;
91                 }
92
93                 case SV_FOOD_PARANOIA:
94                 {
95                         if (!p_ptr->resist_fear)
96                         {
97                                 if (set_afraid(p_ptr, p_ptr->afraid + randint0(10) + 10))
98                                 {
99                                         ident = TRUE;
100                                 }
101                         }
102                         break;
103                 }
104
105                 case SV_FOOD_CONFUSION:
106                 {
107                         if (!p_ptr->resist_conf)
108                         {
109                                 if (set_confused(p_ptr, p_ptr->confused + randint0(10) + 10))
110                                 {
111                                         ident = TRUE;
112                                 }
113                         }
114                         break;
115                 }
116
117                 case SV_FOOD_HALLUCINATION:
118                 {
119                         if (!p_ptr->resist_chaos)
120                         {
121                                 if (set_image(p_ptr, p_ptr->image + randint0(250) + 250))
122                                 {
123                                         ident = TRUE;
124                                 }
125                         }
126                         break;
127                 }
128
129                 case SV_FOOD_PARALYSIS:
130                 {
131                         if (!p_ptr->free_act)
132                         {
133                                 if (set_paralyzed(p_ptr, p_ptr->paralyzed + randint0(10) + 10))
134                                 {
135                                         ident = TRUE;
136                                 }
137                         }
138                         break;
139                 }
140
141                 case SV_FOOD_WEAKNESS:
142                 {
143                         take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);
144                         (void)do_dec_stat(p_ptr, A_STR);
145                         ident = TRUE;
146                         break;
147                 }
148
149                 case SV_FOOD_SICKNESS:
150                 {
151                         take_hit(DAMAGE_NOESCAPE, damroll(6, 6), _("毒入り食料", "poisonous food"), -1);
152                         (void)do_dec_stat(p_ptr, A_CON);
153                         ident = TRUE;
154                         break;
155                 }
156
157                 case SV_FOOD_STUPIDITY:
158                 {
159                         take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);
160                         (void)do_dec_stat(p_ptr, A_INT);
161                         ident = TRUE;
162                         break;
163                 }
164
165                 case SV_FOOD_NAIVETY:
166                 {
167                         take_hit(DAMAGE_NOESCAPE, damroll(8, 8), _("毒入り食料", "poisonous food"), -1);
168                         (void)do_dec_stat(p_ptr, A_WIS);
169                         ident = TRUE;
170                         break;
171                 }
172
173                 case SV_FOOD_UNHEALTH:
174                 {
175                         take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);
176                         (void)do_dec_stat(p_ptr, A_CON);
177                         ident = TRUE;
178                         break;
179                 }
180
181                 case SV_FOOD_DISEASE:
182                 {
183                         take_hit(DAMAGE_NOESCAPE, damroll(10, 10), _("毒入り食料", "poisonous food"), -1);
184                         (void)do_dec_stat(p_ptr, A_STR);
185                         ident = TRUE;
186                         break;
187                 }
188
189                 case SV_FOOD_CURE_POISON:
190                 {
191                         if (set_poisoned(p_ptr, 0)) ident = TRUE;
192                         break;
193                 }
194
195                 case SV_FOOD_CURE_BLINDNESS:
196                 {
197                         if (set_blind(p_ptr, 0)) ident = TRUE;
198                         break;
199                 }
200
201                 case SV_FOOD_CURE_PARANOIA:
202                 {
203                         if (set_afraid(p_ptr, 0)) ident = TRUE;
204                         break;
205                 }
206
207                 case SV_FOOD_CURE_CONFUSION:
208                 {
209                         if (set_confused(p_ptr, 0)) ident = TRUE;
210                         break;
211                 }
212
213                 case SV_FOOD_CURE_SERIOUS:
214                 {
215                         ident = cure_serious_wounds(4, 8);
216                         break;
217                 }
218
219                 case SV_FOOD_RESTORE_STR:
220                 {
221                         if (do_res_stat(p_ptr, A_STR)) ident = TRUE;
222                         break;
223                 }
224
225                 case SV_FOOD_RESTORE_CON:
226                 {
227                         if (do_res_stat(p_ptr, A_CON)) ident = TRUE;
228                         break;
229                 }
230
231                 case SV_FOOD_RESTORING:
232                 {
233                         ident = restore_all_status();
234                         break;
235                 }
236
237
238 #ifdef JP
239                 /* それぞれの食べ物の感想をオリジナルより細かく表現 */
240                 case SV_FOOD_BISCUIT:
241                 {
242                         msg_print("甘くてサクサクしてとてもおいしい。");
243                         ident = TRUE;
244                         break;
245                 }
246
247                 case SV_FOOD_JERKY:
248                 {
249                         msg_print("歯ごたえがあっておいしい。");
250                         ident = TRUE;
251                         break;
252                 }
253
254                 case SV_FOOD_SLIME_MOLD:
255                 {
256                         msg_print("これはなんとも形容しがたい味だ。");
257                         ident = TRUE;
258                         break;
259                 }
260
261                 case SV_FOOD_RATION:
262                 {
263                         msg_print("これはおいしい。");
264                         ident = TRUE;
265                         break;
266                 }
267 #else
268                 case SV_FOOD_RATION:
269                 case SV_FOOD_BISCUIT:
270                 case SV_FOOD_JERKY:
271                 case SV_FOOD_SLIME_MOLD:
272                 {
273                         msg_print("That tastes good.");
274                         ident = TRUE;
275                         break;
276                 }
277 #endif
278
279
280                 case SV_FOOD_WAYBREAD:
281                 {
282                         msg_print(_("これはひじょうに美味だ。", "That tastes good."));
283                         (void)set_poisoned(p_ptr, 0);
284                         (void)hp_player(p_ptr, damroll(4, 8));
285                         ident = TRUE;
286                         break;
287                 }
288
289 #ifdef JP
290                 case SV_FOOD_PINT_OF_ALE:
291                 {
292                         msg_print("のどごし爽やかだ。");
293                         ident = TRUE;
294                         break;
295                 }
296
297                 case SV_FOOD_PINT_OF_WINE:
298                 {
299                         msg_print("That tastes good.");
300                         ident = TRUE;
301                         break;
302                 }
303 #else
304                 case SV_FOOD_PINT_OF_ALE:
305                 case SV_FOOD_PINT_OF_WINE:
306                 {
307                         msg_print("That tastes good.");
308                         ident = TRUE;
309                         break;
310                 }
311 #endif
312
313                 }
314         }
315         p_ptr->update |= (PU_COMBINE | PU_REORDER);
316
317         if (!(object_is_aware(o_ptr)))
318         {
319                 chg_virtue(V_KNOWLEDGE, -1);
320                 chg_virtue(V_PATIENCE, -1);
321                 chg_virtue(V_CHANCE, 1);
322         }
323
324         /* We have tried it */
325         if (o_ptr->tval == TV_FOOD) object_tried(o_ptr);
326
327         /* The player is now aware of the object */
328         if (ident && !object_is_aware(o_ptr))
329         {
330                 object_aware(o_ptr);
331                 gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
332         }
333
334         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
335
336
337         /* Food can feed the player */
338         if (PRACE_IS_(p_ptr, RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE))
339         {
340                 /* Reduced nutritional benefit */
341                 (void)set_food(p_ptr, p_ptr->food + (o_ptr->pval / 10));
342                 msg_print(_("あなたのような者にとって食糧など僅かな栄養にしかならない。",
343                         "Mere victuals hold scant sustenance for a being such as yourself."));
344
345                 if (p_ptr->food < PY_FOOD_ALERT)   /* Hungry */
346                         msg_print(_("あなたの飢えは新鮮な血によってのみ満たされる!",
347                                 "Your hunger can only be satisfied with fresh blood!"));
348         }
349         else if ((PRACE_IS_(p_ptr, RACE_SKELETON) ||
350                 PRACE_IS_(p_ptr, RACE_GOLEM) ||
351                 PRACE_IS_(p_ptr, RACE_ZOMBIE) ||
352                 PRACE_IS_(p_ptr, RACE_SPECTRE)) &&
353                 (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND))
354         {
355                 concptr staff;
356
357                 if (o_ptr->tval == TV_STAFF &&
358                         (item < 0) && (o_ptr->number > 1))
359                 {
360                         msg_print(_("まずは杖を拾わなければ。", "You must first pick up the staffs."));
361                         return;
362                 }
363                 staff = (o_ptr->tval == TV_STAFF) ? _("杖", "staff") : _("魔法棒", "wand");
364
365                 /* "Eat" charges */
366                 if (o_ptr->pval == 0)
367                 {
368                         msg_format(_("この%sにはもう魔力が残っていない。", "The %s has no charges left."), staff);
369                         o_ptr->ident |= (IDENT_EMPTY);
370                         p_ptr->update |= (PU_COMBINE | PU_REORDER);
371                         p_ptr->window |= (PW_INVEN);
372
373                         return;
374                 }
375                 msg_format(_("あなたは%sの魔力をエネルギー源として吸収した。", "You absorb mana of the %s as your energy."), staff);
376
377                 /* Use a single charge */
378                 o_ptr->pval--;
379
380                 /* Eat a charge */
381                 set_food(p_ptr, p_ptr->food + 5000);
382
383                 /* XXX Hack -- unstack if necessary */
384                 if (o_ptr->tval == TV_STAFF &&
385                         (item >= 0) && (o_ptr->number > 1))
386                 {
387                         object_type forge;
388                         object_type *q_ptr;
389                         q_ptr = &forge;
390                         object_copy(q_ptr, o_ptr);
391
392                         /* Modify quantity */
393                         q_ptr->number = 1;
394
395                         /* Restore the charges */
396                         o_ptr->pval++;
397
398                         /* Unstack the used item */
399                         o_ptr->number--;
400                         p_ptr->total_weight -= q_ptr->weight;
401                         item = inven_carry(q_ptr);
402
403                         msg_format(_("杖をまとめなおした。", "You unstack your staff."));
404                 }
405
406                 /* Describe charges in the pack */
407                 if (item >= 0)
408                 {
409                         inven_item_charges(item);
410                 }
411
412                 /* Describe charges on the floor */
413                 else
414                 {
415                         floor_item_charges(0 - item);
416                 }
417
418                 p_ptr->window |= (PW_INVEN | PW_EQUIP);
419
420                 /* Don't eat a staff/wand itself */
421                 return;
422         }
423         else if ((PRACE_IS_(p_ptr, RACE_DEMON) ||
424                 (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)) &&
425                 (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE &&
426                         my_strchr("pht", r_info[o_ptr->pval].d_char)))
427         {
428                 /* Drain vitality of humanoids */
429                 GAME_TEXT o_name[MAX_NLEN];
430                 object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
431                 msg_format(_("%sは燃え上り灰になった。精力を吸収した気がする。", "%^s is burnt to ashes.  You absorb its vitality!"), o_name);
432                 (void)set_food(p_ptr, PY_FOOD_MAX - 1);
433         }
434         else if (PRACE_IS_(p_ptr, RACE_SKELETON))
435         {
436 #if 0
437                 if (o_ptr->tval == TV_SKELETON ||
438                         (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
439                 {
440                         msg_print(_("あなたは骨で自分の体を補った。", "Your body absorbs the bone."));
441                         set_food(p_ptr, p_ptr->food + 5000);
442                 }
443                 else
444 #endif
445
446                         if (!((o_ptr->sval == SV_FOOD_WAYBREAD) ||
447                                 (o_ptr->sval < SV_FOOD_BISCUIT)))
448                         {
449                                 object_type forge;
450                                 object_type *q_ptr = &forge;
451
452                                 msg_print(_("食べ物がアゴを素通りして落ちた!", "The food falls through your jaws!"));
453                                 object_prep(q_ptr, lookup_kind(o_ptr->tval, o_ptr->sval));
454
455                                 /* Drop the object from heaven */
456                                 (void)drop_near(q_ptr, -1, p_ptr->y, p_ptr->x);
457                         }
458                         else
459                         {
460                                 msg_print(_("食べ物がアゴを素通りして落ち、消えた!", "The food falls through your jaws and vanishes!"));
461                         }
462         }
463         else if (PRACE_IS_(p_ptr, RACE_GOLEM) ||
464                 PRACE_IS_(p_ptr, RACE_ZOMBIE) ||
465                 PRACE_IS_(p_ptr, RACE_ENT) ||
466                 PRACE_IS_(p_ptr, RACE_DEMON) ||
467                 PRACE_IS_(p_ptr, RACE_ANDROID) ||
468                 PRACE_IS_(p_ptr, RACE_SPECTRE) ||
469                 (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING))
470         {
471                 msg_print(_("生者の食物はあなたにとってほとんど栄養にならない。", "The food of mortals is poor sustenance for you."));
472                 set_food(p_ptr, p_ptr->food + ((o_ptr->pval) / 20));
473         }
474         else if (o_ptr->tval == TV_FOOD && o_ptr->sval == SV_FOOD_WAYBREAD)
475         {
476                 /* Waybread is always fully satisfying. */
477                 set_food(p_ptr, MAX(p_ptr->food, PY_FOOD_MAX - 1));
478         }
479         else
480         {
481                 /* Food can feed the player */
482                 (void)set_food(p_ptr, p_ptr->food + o_ptr->pval);
483         }
484
485         /* Destroy a food in the pack */
486         if (item >= 0)
487         {
488                 inven_item_increase(item, -1);
489                 inven_item_describe(item);
490                 inven_item_optimize(item);
491         }
492
493         /* Destroy a food on the floor */
494         else
495         {
496                 floor_item_increase(0 - item, -1);
497                 floor_item_describe(0 - item);
498                 floor_item_optimize(0 - item);
499         }
500 }
501
502
503 /*!
504  * @brief 食料を食べるコマンドのメインルーチン /
505  * Eat some food (from the pack or floor)
506  * @return なし
507  */
508 void do_cmd_eat_food(void)
509 {
510         OBJECT_IDX item;
511         concptr        q, s;
512
513         if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
514         {
515                 set_action(ACTION_NONE);
516         }
517
518         /* Restrict choices to food */
519         item_tester_hook = item_tester_hook_eatable;
520
521         q = _("どれを食べますか? ", "Eat which item? ");
522         s = _("食べ物がない。", "You have nothing to eat.");
523
524         if (!choose_object(&item, q, s, (USE_INVEN | USE_FLOOR), 0)) return;
525
526         /* Eat the object */
527         exe_eat_food(item);
528 }
529