OSDN Git Service

93f388a74f6850ac8d43d87e0a0f42b250217ef5
[hengbandforosx/hengbandosx.git] / src / player / digestion-processor.cpp
1 #include "player/digestion-processor.h"
2 #include "avatar/avatar.h"
3 #include "core/disturbance.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "core/speed-table.h"
7 #include "core/stuff-handler.h"
8 #include "floor/wild.h"
9 #include "game-option/disturbance-options.h"
10 #include "main/sound-definitions-table.h"
11 #include "main/sound-of-music.h"
12 #include "object-enchant/trc-types.h"
13 #include "player-base/player-class.h"
14 #include "player-info/monk-data-type.h"
15 #include "player-info/samurai-data-type.h"
16 #include "player/player-damage.h"
17 #include "player/player-status.h"
18 #include "player/special-defense-types.h"
19 #include "status/bad-status-setter.h"
20 #include "system/player-type-definition.h"
21 #include "view/display-messages.h"
22 #include "world/world.h"
23
24 /*!
25  * @brief 10ゲームターンが進行するごとにプレイヤーの腹を減らす
26  * @param player_ptr プレイヤーへの参照ポインタ
27  */
28 void starve_player(PlayerType *player_ptr)
29 {
30     if (player_ptr->phase_out)
31         return;
32
33     if (player_ptr->food >= PY_FOOD_MAX) {
34         (void)set_food(player_ptr, player_ptr->food - 100);
35     } else if (!(w_ptr->game_turn % (TURNS_PER_TICK * 5))) {
36         int digestion = speed_to_energy(player_ptr->pspeed);
37         if (player_ptr->regenerate)
38             digestion += 20;
39         PlayerClass pc(player_ptr);
40         if (!pc.monk_stance_is(MonkStanceType::NONE) || !pc.samurai_stance_is(SamuraiStanceType::NONE))
41             digestion += 20;
42         if (player_ptr->cursed.has(CurseTraitType::FAST_DIGEST))
43             digestion += 30;
44
45         if (player_ptr->slow_digest)
46             digestion -= 5;
47
48         if (digestion < 1)
49             digestion = 1;
50         if (digestion > 100)
51             digestion = 100;
52
53         (void)set_food(player_ptr, player_ptr->food - digestion);
54     }
55
56     if ((player_ptr->food >= PY_FOOD_FAINT))
57         return;
58
59     if (!player_ptr->paralyzed && (randint0(100) < 10)) {
60         msg_print(_("あまりにも空腹で気絶してしまった。", "You faint from the lack of food."));
61         disturb(player_ptr, true, true);
62         (void)BadStatusSetter(player_ptr).mod_paralysis(1 + randint0(5));
63     }
64
65     if (player_ptr->food < PY_FOOD_STARVE) {
66         HIT_POINT dam = (PY_FOOD_STARVE - player_ptr->food) / 10;
67         if (!is_invuln(player_ptr))
68             take_hit(player_ptr, DAMAGE_LOSELIFE, dam, _("空腹", "starvation"));
69     }
70 }
71
72 /*!
73  * @brief 空腹状態をセットする / Set "food", notice observable changes
74  * @param v 継続時間
75  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す
76  * @details
77  * Set "", notice observable changes\n
78  *\n
79  * The "food" variable can get as large as 20000, allowing the
80  * addition of the most "filling" item, Elvish Waybread, which adds
81  * 7500 food units, without overflowing the 32767 maximum limit.\n
82  *\n
83  * Perhaps we should disturb the player with various messages,
84  * especially messages about hunger status changes.  \n
85  *\n
86  * Digestion of food is handled in "dungeon.c", in which, normally,
87  * the player digests about 20 food units per 100 game turns, more
88  * when "fast", more when "regenerating", less with "slow digestion",
89  * but when the player is "gorged", he digests 100 food units per 10
90  * game turns, or a full 1000 food units per 100 game turns.\n
91  *\n
92  * Note that the player's speed is reduced by 10 units while gorged,
93  * so if the player eats a single food ration (5000 food units) when
94  * full (15000 food units), he will be gorged for (5000/100)*10 = 500
95  * game turns, or 500/(100/5) = 25 player turns (if nothing else is
96  * affecting the player speed).\n
97  */
98 bool set_food(PlayerType *player_ptr, TIME_EFFECT v)
99 {
100     int old_aux, new_aux;
101
102     bool notice = false;
103     v = (v > 20000) ? 20000 : (v < 0) ? 0 : v;
104     if (player_ptr->food < PY_FOOD_FAINT) {
105         old_aux = 0;
106     } else if (player_ptr->food < PY_FOOD_WEAK) {
107         old_aux = 1;
108     } else if (player_ptr->food < PY_FOOD_ALERT) {
109         old_aux = 2;
110     } else if (player_ptr->food < PY_FOOD_FULL) {
111         old_aux = 3;
112     } else if (player_ptr->food < PY_FOOD_MAX) {
113         old_aux = 4;
114     } else {
115         old_aux = 5;
116     }
117
118     if (v < PY_FOOD_FAINT) {
119         new_aux = 0;
120     } else if (v < PY_FOOD_WEAK) {
121         new_aux = 1;
122     } else if (v < PY_FOOD_ALERT) {
123         new_aux = 2;
124     } else if (v < PY_FOOD_FULL) {
125         new_aux = 3;
126     } else if (v < PY_FOOD_MAX) {
127         new_aux = 4;
128     } else {
129         new_aux = 5;
130     }
131
132     if (old_aux < 1 && new_aux > 0)
133         chg_virtue(player_ptr, V_PATIENCE, 2);
134     else if (old_aux < 3 && (old_aux != new_aux))
135         chg_virtue(player_ptr, V_PATIENCE, 1);
136     if (old_aux == 2)
137         chg_virtue(player_ptr, V_TEMPERANCE, 1);
138     if (old_aux == 0)
139         chg_virtue(player_ptr, V_TEMPERANCE, -1);
140
141     if (new_aux > old_aux) {
142         switch (new_aux) {
143         case 1:
144             msg_print(_("まだ空腹で倒れそうだ。", "You are still weak."));
145             break;
146         case 2:
147             msg_print(_("まだ空腹だ。", "You are still hungry."));
148             break;
149         case 3:
150             msg_print(_("空腹感がおさまった。", "You are no longer hungry."));
151             break;
152         case 4:
153             msg_print(_("満腹だ!", "You are full!"));
154             break;
155
156         case 5:
157             msg_print(_("食べ過ぎだ!", "You have gorged yourself!"));
158             chg_virtue(player_ptr, V_HARMONY, -1);
159             chg_virtue(player_ptr, V_PATIENCE, -1);
160             chg_virtue(player_ptr, V_TEMPERANCE, -2);
161             break;
162         }
163
164         notice = true;
165     } else if (new_aux < old_aux) {
166         switch (new_aux) {
167         case 0:
168             sound(SOUND_FAINT);
169             msg_print(_("あまりにも空腹で気を失ってしまった!", "You are getting faint from hunger!"));
170             break;
171         case 1:
172             sound(SOUND_WEAK);
173             msg_print(_("お腹が空いて倒れそうだ。", "You are getting weak from hunger!"));
174             break;
175         case 2:
176             sound(SOUND_HUNGRY);
177             msg_print(_("お腹が空いてきた。", "You are getting hungry."));
178             break;
179         case 3:
180             msg_print(_("満腹感がなくなった。", "You are no longer full."));
181             break;
182         case 4:
183             msg_print(_("やっとお腹がきつくなくなった。", "You are no longer gorged."));
184             break;
185         }
186
187         if (player_ptr->wild_mode && (new_aux < 2)) {
188             change_wild_mode(player_ptr, false);
189         }
190
191         notice = true;
192     }
193
194     player_ptr->food = v;
195     if (!notice)
196         return false;
197
198     if (disturb_state)
199         disturb(player_ptr, false, false);
200     player_ptr->update |= (PU_BONUS);
201     player_ptr->redraw |= (PR_HUNGER);
202     handle_stuff(player_ptr);
203
204     return true;
205 }