OSDN Git Service

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