OSDN Git Service

Merge pull request #1054 from shimitei/feature/#1022_extend_autopick_max_line
[hengbandforosx/hengbandosx.git] / src / cmd-action / cmd-move.cpp
1 #include "cmd-action/cmd-move.h"
2 #include "action/action-limited.h"
3 #include "action/movement-execution.h"
4 #include "action/run-execution.h"
5 #include "cmd-io/cmd-save.h"
6 #include "core/asking-player.h"
7 #include "core/disturbance.h"
8 #include "core/player-redraw-types.h"
9 #include "core/player-update-types.h"
10 #include "core/stuff-handler.h"
11 #include "dungeon/dungeon.h"
12 #include "dungeon/quest.h"
13 #include "floor/cave.h"
14 #include "floor/floor-mode-changer.h"
15 #include "floor/wild.h"
16 #include "game-option/birth-options.h"
17 #include "game-option/input-options.h"
18 #include "game-option/play-record-options.h"
19 #include "game-option/special-options.h"
20 #include "game-option/map-screen-options.h"
21 #include "grid/feature.h"
22 #include "grid/grid.h"
23 #include "info-reader/fixed-map-parser.h"
24 #include "io/input-key-requester.h"
25 #include "io/write-diary.h"
26 #include "mind/mind-ninja.h"
27 #include "player-info/avatar.h"
28 #include "player-status/player-energy.h"
29 #include "player/attack-defense-types.h"
30 #include "player/player-move.h"
31 #include "player/player-status.h"
32 #include "player/special-defense-types.h"
33 #include "spell-realm/spells-hex.h"
34 #include "spell-realm/spells-song.h"
35 #include "status/action-setter.h"
36 #include "system/floor-type-definition.h"
37 #include "system/player-type-definition.h"
38 #include "target/target-getter.h"
39 #include "util/bit-flags-calculator.h"
40 #include "view/display-messages.h"
41
42 /*!
43  * @brief フロア脱出時に出戻りが不可能だった場合に警告を加える処理
44  * @param down_stair TRUEならば階段を降りる処理、FALSEなら階段を昇る処理による内容
45  * @return フロア移動を実際に行うならTRUE、キャンセルする場合はFALSE
46  */
47 static bool confirm_leave_level(player_type *creature_ptr, bool down_stair)
48 {
49     quest_type *q_ptr = &quest[creature_ptr->current_floor_ptr->inside_quest];
50     if (confirm_quest && creature_ptr->current_floor_ptr->inside_quest
51         && (q_ptr->type == QUEST_TYPE_RANDOM || (q_ptr->flags & QUEST_FLAG_ONCE && q_ptr->status != QUEST_STATUS_COMPLETED)
52             || (q_ptr->flags & QUEST_FLAG_TOWER
53                 && ((q_ptr->status != QUEST_STATUS_STAGE_COMPLETED) || (down_stair && (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED)))))) {
54         msg_print(_("この階を一度去ると二度と戻って来られません。", "You can't come back here once you leave this floor."));
55         return get_check(_("本当にこの階を去りますか?", "Really leave this floor? "));
56     }
57
58     return TRUE;
59 }
60
61 /*!
62  * @brief 階段を使って階層を昇る処理 / Go up one level
63  */
64 void do_cmd_go_up(player_type *creature_ptr)
65 {
66     bool go_up = FALSE;
67     grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
68     feature_type *f_ptr = &f_info[g_ptr->feat];
69     int up_num = 0;
70     if (creature_ptr->special_defense & KATA_MUSOU)
71         set_action(creature_ptr, ACTION_NONE);
72
73     if (!has_flag(f_ptr->flags, FF_LESS)) {
74         msg_print(_("ここには上り階段が見当たらない。", "I see no up staircase here."));
75         return;
76     }
77
78     if (has_flag(f_ptr->flags, FF_QUEST)) {
79         if (!confirm_leave_level(creature_ptr, FALSE))
80             return;
81
82         if (is_echizen(creature_ptr))
83             msg_print(_("なんだこの階段は!", "What's this STAIRWAY!"));
84         else
85             msg_print(_("上の階に登った。", "You enter the up staircase."));
86
87         leave_quest_check(creature_ptr);
88         creature_ptr->current_floor_ptr->inside_quest = g_ptr->special;
89         if (!quest[creature_ptr->current_floor_ptr->inside_quest].status) {
90             if (quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) {
91                 init_flags = INIT_ASSIGN;
92                 parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
93             }
94
95             quest[creature_ptr->current_floor_ptr->inside_quest].status = QUEST_STATUS_TAKEN;
96         }
97
98         if (!creature_ptr->current_floor_ptr->inside_quest) {
99             creature_ptr->current_floor_ptr->dun_level = 0;
100             creature_ptr->word_recall = 0;
101         }
102
103         creature_ptr->leaving = TRUE;
104         creature_ptr->oldpx = 0;
105         creature_ptr->oldpy = 0;
106         PlayerEnergy(creature_ptr).set_player_turn_energy(100);
107         return;
108     }
109
110     if (!is_in_dungeon(creature_ptr))
111         go_up = TRUE;
112     else
113         go_up = confirm_leave_level(creature_ptr, FALSE);
114
115     if (!go_up)
116         return;
117
118     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
119
120     if (autosave_l)
121         do_cmd_save_game(creature_ptr, TRUE);
122
123     if (creature_ptr->current_floor_ptr->inside_quest && quest[creature_ptr->current_floor_ptr->inside_quest].type == QUEST_TYPE_RANDOM) {
124         leave_quest_check(creature_ptr);
125         creature_ptr->current_floor_ptr->inside_quest = 0;
126     }
127
128     if (creature_ptr->current_floor_ptr->inside_quest && quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) {
129         leave_quest_check(creature_ptr);
130         creature_ptr->current_floor_ptr->inside_quest = g_ptr->special;
131         creature_ptr->current_floor_ptr->dun_level = 0;
132         up_num = 0;
133     } else {
134         if (has_flag(f_ptr->flags, FF_SHAFT)) {
135             prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP | CFM_SHAFT);
136             up_num = 2;
137         } else {
138             prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_UP);
139             up_num = 1;
140         }
141
142         if (creature_ptr->current_floor_ptr->dun_level - up_num < d_info[creature_ptr->dungeon_idx].mindepth)
143             up_num = creature_ptr->current_floor_ptr->dun_level;
144     }
145
146     if (record_stair)
147         exe_write_diary(creature_ptr, DIARY_STAIR, 0 - up_num, _("階段を上った", "climbed up the stairs to"));
148
149     if (is_echizen(creature_ptr))
150         msg_print(_("なんだこの階段は!", "What's this STAIRWAY!"));
151     else if (up_num == creature_ptr->current_floor_ptr->dun_level) {
152         msg_print(_("地上に戻った。", "You go back to the surface."));
153         creature_ptr->word_recall = 0;
154     }
155     else
156         msg_print(_("階段を上って新たなる迷宮へと足を踏み入れた。", "You enter a maze of up staircases."));
157
158     creature_ptr->leaving = TRUE;
159 }
160
161 /*!
162  * @brief 階段を使って階層を降りる処理 / Go down one level
163  * @param creature_ptr プレーヤーへの参照ポインタ
164  */
165 void do_cmd_go_down(player_type *creature_ptr)
166 {
167     bool fall_trap = FALSE;
168     int down_num = 0;
169     if (creature_ptr->special_defense & KATA_MUSOU)
170         set_action(creature_ptr, ACTION_NONE);
171
172     grid_type *g_ptr = &creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x];
173     feature_type *f_ptr = &f_info[g_ptr->feat];
174     if (!has_flag(f_ptr->flags, FF_MORE)) {
175         msg_print(_("ここには下り階段が見当たらない。", "I see no down staircase here."));
176         return;
177     }
178
179     if (has_flag(f_ptr->flags, FF_TRAP))
180         fall_trap = TRUE;
181
182     if (has_flag(f_ptr->flags, FF_QUEST_ENTER)) {
183         do_cmd_quest(creature_ptr);
184         return;
185     }
186
187     if (has_flag(f_ptr->flags, FF_QUEST)) {
188         if (!confirm_leave_level(creature_ptr, TRUE))
189             return;
190
191         if (is_echizen(creature_ptr))
192             msg_print(_("なんだこの階段は!", "What's this STAIRWAY!"));
193         else
194             msg_print(_("下の階に降りた。", "You enter the down staircase."));
195
196         leave_quest_check(creature_ptr);
197         leave_tower_check(creature_ptr);
198         creature_ptr->current_floor_ptr->inside_quest = g_ptr->special;
199         if (!quest[creature_ptr->current_floor_ptr->inside_quest].status) {
200             if (quest[creature_ptr->current_floor_ptr->inside_quest].type != QUEST_TYPE_RANDOM) {
201                 init_flags = INIT_ASSIGN;
202                 parse_fixed_map(creature_ptr, "q_info.txt", 0, 0, 0, 0);
203             }
204
205             quest[creature_ptr->current_floor_ptr->inside_quest].status = QUEST_STATUS_TAKEN;
206         }
207
208         if (!creature_ptr->current_floor_ptr->inside_quest) {
209             creature_ptr->current_floor_ptr->dun_level = 0;
210             creature_ptr->word_recall = 0;
211         }
212
213         creature_ptr->leaving = TRUE;
214         creature_ptr->oldpx = 0;
215         creature_ptr->oldpy = 0;
216         PlayerEnergy(creature_ptr).set_player_turn_energy(100);
217         return;
218     }
219
220     DUNGEON_IDX target_dungeon = 0;
221     if (!is_in_dungeon(creature_ptr)) {
222         target_dungeon = has_flag(f_ptr->flags, FF_ENTRANCE) ? g_ptr->special : DUNGEON_ANGBAND;
223         if (ironman_downward && (target_dungeon != DUNGEON_ANGBAND)) {
224             msg_print(_("ダンジョンの入口は塞がれている!", "The entrance of this dungeon is closed!"));
225             return;
226         }
227
228         if (!max_dlv[target_dungeon]) {
229             msg_format(_("ここには%sの入り口(%d階相当)があります", "There is the entrance of %s (Danger level: %d)"), d_info[target_dungeon].name.c_str(),
230                 d_info[target_dungeon].mindepth);
231             if (!get_check(_("本当にこのダンジョンに入りますか?", "Do you really get in this dungeon? ")))
232                 return;
233         }
234
235         creature_ptr->oldpx = creature_ptr->x;
236         creature_ptr->oldpy = creature_ptr->y;
237         creature_ptr->dungeon_idx = target_dungeon;
238         prepare_change_floor_mode(creature_ptr, CFM_FIRST_FLOOR);
239     }
240
241     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
242     if (autosave_l)
243         do_cmd_save_game(creature_ptr, TRUE);
244
245     if (has_flag(f_ptr->flags, FF_SHAFT))
246         down_num += 2;
247     else
248         down_num += 1;
249
250     if (!is_in_dungeon(creature_ptr)) {
251         creature_ptr->enter_dungeon = TRUE;
252         down_num = d_info[creature_ptr->dungeon_idx].mindepth;
253     }
254
255     if (record_stair) {
256         if (fall_trap)
257             exe_write_diary(creature_ptr, DIARY_STAIR, down_num, _("落とし戸に落ちた", "fell through a trap door"));
258         else
259             exe_write_diary(creature_ptr, DIARY_STAIR, down_num, _("階段を下りた", "climbed down the stairs to"));
260     }
261
262     if (fall_trap) {
263         msg_print(_("わざと落とし戸に落ちた。", "You deliberately jump through the trap door."));
264     } else {
265         if (target_dungeon) {
266             msg_format(_("%sへ入った。", "You entered %s."), d_info[creature_ptr->dungeon_idx].text.c_str());
267         } else {
268             if (is_echizen(creature_ptr))
269                 msg_print(_("なんだこの階段は!", "What's this STAIRWAY!"));
270             else
271                 msg_print(_("階段を下りて新たなる迷宮へと足を踏み入れた。", "You enter a maze of down staircases."));
272         }
273     }
274
275     creature_ptr->leaving = TRUE;
276
277     if (fall_trap) {
278         prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT);
279         return;
280     }
281
282     if (has_flag(f_ptr->flags, FF_SHAFT))
283         prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_SHAFT);
284     else
285         prepare_change_floor_mode(creature_ptr, CFM_SAVE_FLOORS | CFM_DOWN);
286 }
287
288 /*!
289  * @brief 「歩く」動作コマンドのメインルーチン /
290  * Support code for the "Walk" and "Jump" commands
291  * @param creature_ptr プレーヤーへの参照ポインタ
292  * @param pickup アイテムの自動拾いを行うならTRUE
293  */
294 void do_cmd_walk(player_type *creature_ptr, bool pickup)
295 {
296     if (command_arg) {
297         command_rep = command_arg - 1;
298         creature_ptr->redraw |= PR_STATE;
299         command_arg = 0;
300     }
301
302     bool more = FALSE;
303     DIRECTION dir;
304     if (get_rep_dir(creature_ptr, &dir, FALSE)) {
305         PlayerEnergy energy(creature_ptr);
306         energy.set_player_turn_energy(100);
307         if ((dir != 5) && (creature_ptr->special_defense & KATA_MUSOU))
308             set_action(creature_ptr, ACTION_NONE);
309
310         if (creature_ptr->wild_mode) {
311             energy.mul_player_turn_energy((MAX_HGT + MAX_WID) / 2);
312         }
313
314         if (creature_ptr->action == ACTION_HAYAGAKE) {
315             auto energy_use = (ENERGY)(creature_ptr->energy_use * (45 - (creature_ptr->lev / 2)) / 100);
316             energy.set_player_turn_energy(energy_use);
317         }
318
319         exe_movement(creature_ptr, dir, pickup, FALSE);
320         more = TRUE;
321     }
322
323     if (creature_ptr->wild_mode && !cave_has_flag_bold(creature_ptr->current_floor_ptr, creature_ptr->y, creature_ptr->x, FF_TOWN)) {
324         int tmp = 120 + creature_ptr->lev * 10 - wilderness[creature_ptr->y][creature_ptr->x].level + 5;
325         if (tmp < 1)
326             tmp = 1;
327
328         if (((wilderness[creature_ptr->y][creature_ptr->x].level + 5) > (creature_ptr->lev / 2)) && randint0(tmp) < (21 - creature_ptr->skill_stl)) {
329             msg_print(_("襲撃だ!", "You are ambushed !"));
330             creature_ptr->oldpy = randint1(MAX_HGT - 2);
331             creature_ptr->oldpx = randint1(MAX_WID - 2);
332             change_wild_mode(creature_ptr, TRUE);
333             PlayerEnergy(creature_ptr).set_player_turn_energy(100);
334         }
335     }
336
337     if (!more)
338         disturb(creature_ptr, FALSE, FALSE);
339 }
340
341 /*!
342  * @brief 「走る」動作コマンドのメインルーチン /
343  * Start running.
344  * @param creature_ptr プレーヤーへの参照ポインタ
345  */
346 void do_cmd_run(player_type *creature_ptr)
347 {
348     DIRECTION dir;
349     if (cmd_limit_confused(creature_ptr))
350         return;
351
352     if (creature_ptr->special_defense & KATA_MUSOU)
353         set_action(creature_ptr, ACTION_NONE);
354
355     if (get_rep_dir(creature_ptr, &dir, FALSE)) {
356         creature_ptr->running = (command_arg ? command_arg : 1000);
357         run_step(creature_ptr, dir);
358     }
359 }
360
361 /*!
362  * @brief 「留まる」動作コマンドのメインルーチン /
363  * Stay still.  Search.  Enter stores.
364  * Pick up treasure if "pickup" is true.
365  * @param creature_ptr プレーヤーへの参照ポインタ
366  * @param pickup アイテムの自動拾いを行うならTRUE
367  */
368 void do_cmd_stay(player_type *creature_ptr, bool pickup)
369 {
370     u32b mpe_mode = MPE_STAYING | MPE_ENERGY_USE;
371     if (command_arg) {
372         command_rep = command_arg - 1;
373         creature_ptr->redraw |= (PR_STATE);
374         command_arg = 0;
375     }
376
377     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
378     if (pickup)
379         mpe_mode |= MPE_DO_PICKUP;
380
381     (void)move_player_effect(creature_ptr, creature_ptr->y, creature_ptr->x, mpe_mode);
382 }
383
384 /*!
385  * @brief 「休む」動作コマンドのメインルーチン /
386  * Resting allows a player to safely restore his hp     -RAK-
387  * @param creature_ptr プレーヤーへの参照ポインタ
388  */
389 void do_cmd_rest(player_type *creature_ptr)
390 {
391     set_action(creature_ptr, ACTION_NONE);
392     if ((creature_ptr->pclass == CLASS_BARD) && ((get_singing_song_effect(creature_ptr) != 0)|| (get_interrupting_song_effect(creature_ptr) != 0)))
393         stop_singing(creature_ptr);
394
395     if (hex_spelling_any(creature_ptr))
396         stop_hex_spell_all(creature_ptr);
397
398     if (command_arg <= 0) {
399         concptr p = _("休憩 (0-9999, '*' で HP/MP全快, '&' で必要なだけ): ", "Rest (0-9999, '*' for HP/SP, '&' as needed): ");
400         char out_val[80];
401         strcpy(out_val, "&");
402         if (!get_string(p, out_val, 4))
403             return;
404
405         if (out_val[0] == '&') {
406             command_arg = COMMAND_ARG_REST_UNTIL_DONE;
407         } else if (out_val[0] == '*') {
408             command_arg = COMMAND_ARG_REST_FULL_HEALING;
409         } else {
410             command_arg = (COMMAND_ARG)atoi(out_val);
411             if (command_arg <= 0)
412                 return;
413         }
414     }
415
416     if (command_arg > 9999)
417         command_arg = 9999;
418
419     if (creature_ptr->special_defense & NINJA_S_STEALTH)
420         set_superstealth(creature_ptr, FALSE);
421
422     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
423     if (command_arg > 100)
424         chg_virtue(creature_ptr, V_DILIGENCE, -1);
425
426     if ((creature_ptr->chp == creature_ptr->mhp) && (creature_ptr->csp == creature_ptr->msp) && !creature_ptr->blind && !creature_ptr->confused
427         && !creature_ptr->poisoned && !creature_ptr->afraid && !creature_ptr->stun && !creature_ptr->cut && !creature_ptr->slow && !creature_ptr->paralyzed
428         && !creature_ptr->image && !creature_ptr->word_recall && !creature_ptr->alter_reality)
429         chg_virtue(creature_ptr, V_DILIGENCE, -1);
430
431     creature_ptr->resting = command_arg;
432     creature_ptr->action = ACTION_REST;
433     creature_ptr->update |= PU_BONUS;
434     creature_ptr->redraw |= (PR_STATE);
435     handle_stuff(creature_ptr);
436     term_fresh();
437 }