OSDN Git Service

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