OSDN Git Service

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