OSDN Git Service

Merge pull request #1463 from habu1010/feature/fix-x11-resource-leak
[hengbandforosx/hengbandosx.git] / src / cmd-building / cmd-inn.cpp
1 #include "cmd-building/cmd-inn.h"
2 #include "cmd-item/cmd-magiceat.h"
3 #include "core/turn-compensator.h"
4 #include "game-option/birth-options.h"
5 #include "io/write-diary.h"
6 #include "market/building-actions-table.h"
7 #include "market/bounty.h"
8 #include "status/bad-status-setter.h"
9 #include "player/digestion-processor.h"
10 #include "player/eldritch-horror.h"
11 #include "player/player-race-types.h"
12 #include "player/player-race.h"
13 #include "store/rumor.h"
14 #include "system/player-type-definition.h"
15 #include "view/display-messages.h"
16 #include "world/world.h"
17
18 /*!
19  * @brief 宿屋で食事を摂る
20  * @param customer_ptr プレーヤーへの参照ポインタ
21  * @return 満腹ならFALSE、そうでないならTRUE
22  */
23 static bool buy_food(player_type *customer_ptr)
24 {
25         if (customer_ptr->food >= PY_FOOD_FULL)
26         {
27                 msg_print(_("今は満腹だ。", "You are full now."));
28                 return false;
29         }
30
31         msg_print(_("バーテンはいくらかの食べ物とビールをくれた。", "The barkeep gives you some gruel and a beer."));
32         (void)set_food(customer_ptr, PY_FOOD_MAX - 1);
33         return true;
34 }
35
36
37 /*!
38  * @brief 健康体しか宿屋に泊めない処理
39  * @param customer_ptr プレーヤーへの参照ポインタ
40  * @return 毒でも切り傷でもないならTRUE、そうでないならFALSE
41  */
42 static bool is_healthy_stay(player_type *customer_ptr)
43 {
44         if (!customer_ptr->poisoned && !customer_ptr->cut) return true;
45
46         msg_print(_("あなたに必要なのは部屋ではなく、治療者です。", "You need a healer, not a room."));
47         msg_print(nullptr);
48         msg_print(_("すみません、でもうちで誰かに死なれちゃ困りますんで。", "Sorry, but I don't want anyone dying in here."));
49         return false;
50 }
51
52
53 #ifdef JP
54 static bool is_player_undead(player_type *customer_ptr)
55 {
56         return player_race_life(customer_ptr, true) == PlayerRaceLife::UNDEAD;
57 }
58 #endif
59
60
61 /*!
62  * @brief 宿屋に泊まったことを日記に残す
63  * @param customer_ptr プレーヤーへの参照ポインタ
64  * @param prev_hour 宿屋に入った直後のゲーム内時刻
65  */
66 static void write_diary_stay_inn(player_type *customer_ptr, int prev_hour)
67 {
68         if ((prev_hour >= 6) && (prev_hour < 18))
69         {
70                 concptr stay_message = _(is_player_undead(customer_ptr) ? "宿屋に泊まった。" : "日が暮れるまで宿屋で過ごした。", "stayed during the day at the inn.");
71                 exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, stay_message);
72                 return;
73         }
74
75         concptr stay_message = _(is_player_undead(customer_ptr) ? "夜が明けるまで宿屋で過ごした。" : "宿屋に泊まった。", "stayed overnight at the inn.");
76         exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, stay_message);
77 }
78
79
80 /*!
81  * @brief 宿泊によってゲーム内ターンを経過させる
82  * @param なし
83  */
84 static void pass_game_turn_by_stay(void)
85 {
86         int32_t oldturn = current_world_ptr->game_turn;
87         current_world_ptr->game_turn =
88                 (current_world_ptr->game_turn / (TURNS_PER_TICK * TOWN_DAWN / 2) + 1) *
89                 (TURNS_PER_TICK * TOWN_DAWN / 2);
90         if (current_world_ptr->dungeon_turn >= current_world_ptr->dungeon_turn_limit)
91                 return;
92
93         current_world_ptr->dungeon_turn += MIN((current_world_ptr->game_turn - oldturn), TURNS_PER_TICK * 250) * INN_DUNGEON_TURN_ADJ;
94         if (current_world_ptr->dungeon_turn > current_world_ptr->dungeon_turn_limit)
95                 current_world_ptr->dungeon_turn = current_world_ptr->dungeon_turn_limit;
96 }
97
98
99 /*!
100  * @brief 悪夢モードなら悪夢を見せる
101  * @param customer_ptr プレーヤーへの参照ポインタ
102  * @return 悪夢モードならばTRUE
103  */
104 static bool has_a_nightmare(player_type *customer_ptr)
105 {
106         if (!ironman_nightmare) return false;
107
108         msg_print(_("眠りに就くと恐ろしい光景が心をよぎった。", "Horrible visions flit through your mind as you sleep."));
109
110         while (true)
111         {
112                 sanity_blast(customer_ptr, nullptr, false);
113                 if (!one_in_(3)) break;
114         }
115
116         msg_print(_("あなたは絶叫して目を覚ました。", "You awake screaming."));
117         exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, _("悪夢にうなされてよく眠れなかった。", "had a nightmare."));
118         return true;
119 }
120
121
122 /*!
123  * @brief 体調を元に戻す
124  * @param customer_ptr プレーヤーへの参照ポインタ
125  */
126 static void back_to_health(player_type *customer_ptr)
127 {
128         set_blind(customer_ptr, 0);
129         set_confused(customer_ptr, 0);
130         customer_ptr->stun = 0;
131         customer_ptr->chp = customer_ptr->mhp;
132         customer_ptr->csp = customer_ptr->msp;
133 }
134
135
136 /*!
137  * @brief 魔力喰いの残り回数回復(本当? 要調査)
138  * @param customer_ptr プレーヤーへの参照ポインタ
139  */
140 static void charge_magic_eating_energy(player_type *customer_ptr)
141 {
142         if (customer_ptr->pclass != CLASS_MAGIC_EATER)
143                 return;
144
145         int i;
146         for (i = 0; i < 72; i++)
147         {
148                 customer_ptr->magic_num1[i] = customer_ptr->magic_num2[i] * EATER_CHARGE;
149         }
150
151         for (; i < MAX_SPELLS; i++)
152         {
153                 customer_ptr->magic_num1[i] = 0;
154         }
155 }
156
157
158 /*!
159  * @brief リフレッシュ結果を画面に表示する
160  * @param customer_ptr プレーヤーへの参照ポインタ
161  * @param prev_hour 宿屋に入った直後のゲーム内時刻
162  */
163 static void display_stay_result(player_type *customer_ptr, int prev_hour)
164 {
165         if ((prev_hour >= 6) && (prev_hour < 18))
166         {
167 #if JP
168                 char refresh_message_jp[50];
169                 sprintf(refresh_message_jp, "%s%s%s", "あなたはリフレッシュして目覚め、", is_player_undead(customer_ptr) ? "夜" : "夕方", "を迎えた。");
170                 msg_print(refresh_message_jp);
171 #else
172                 msg_print("You awake refreshed for the evening.");
173 #endif
174                 concptr awake_message = _(is_player_undead(customer_ptr) ? "すがすがしい夜を迎えた。" : "夕方を迎えた。", "awoke refreshed.");
175                 exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, awake_message);
176                 return;
177         }
178
179         msg_print(_("あなたはリフレッシュして目覚め、新たな日を迎えた。", "You awake refreshed for the new day."));
180         concptr awake_message = _(is_player_undead(customer_ptr) ? "すがすがしい朝を迎えた。" : "朝を迎えた。", "awoke refreshed.");
181         exe_write_diary(customer_ptr, DIARY_DESCRIPTION, 0, awake_message);
182 }
183
184
185 /*!
186  * @brief 宿屋への宿泊実行処理
187  * @param customer_ptr プレーヤーへの参照ポインタ
188  * @return 泊まれたらTRUE
189  */
190 static bool stay_inn(player_type *customer_ptr)
191 {
192         if (!is_healthy_stay(customer_ptr)) return false;
193
194         int prev_day, prev_hour, prev_min;
195         extract_day_hour_min(customer_ptr, &prev_day, &prev_hour, &prev_min);
196         write_diary_stay_inn(customer_ptr, prev_hour);
197
198         pass_game_turn_by_stay();
199         prevent_turn_overflow(customer_ptr);
200
201         if ((prev_hour >= 18) && (prev_hour <= 23)) {
202                 determine_daily_bounty(customer_ptr, false); /* Update daily bounty */
203                 exe_write_diary(customer_ptr, DIARY_DIALY, 0, nullptr);
204         }
205
206         customer_ptr->chp = customer_ptr->mhp;
207         if (has_a_nightmare(customer_ptr)) return true;
208
209         back_to_health(customer_ptr);
210         charge_magic_eating_energy(customer_ptr);
211
212         display_stay_result(customer_ptr, prev_hour);
213         return true;
214 }
215
216
217 /*!
218  * @brief 宿屋を利用する
219  * @param customer_ptr プレーヤーへの参照ポインタ
220  * @param cmd 宿屋の利用施設ID
221  * @return 施設の利用が実際に行われたらTRUE
222  * @details inn commands
223  * Note that resting for the night was a perfect way to avoid player
224  * ghosts in the town *if* you could only make it to the inn in time (-:
225  * Now that the ghosts are temporarily disabled in 2.8.X, this function
226  * will not be that useful.  I will keep it in the hopes the player
227  * ghost code does become a reality again. Does help to avoid filthy urchins.
228  * Resting at night is also a quick way to restock stores -KMW-
229  * @todo 悪夢を見る前後に全回復しているが、何か意図がある?
230  */
231 bool inn_comm(player_type *customer_ptr, int cmd)
232 {
233         switch (cmd)
234         {
235         case BACT_FOOD:
236                 return buy_food(customer_ptr);
237         case BACT_REST:
238                 return stay_inn(customer_ptr);
239         case BACT_RUMORS:
240                 display_rumor(customer_ptr, true);
241                 return true;
242         default:
243                 //!< @todo リファクタリング前のコードもTRUEだった、FALSEにすべきでは.
244                 return true;
245         }
246 }