OSDN Git Service

[fix] #41503 超能力者でゲームを開始しようとするとクラッシュ
[hengband/hengband.git] / src / core / game-closer.c
1 #include "core/game-closer.h"
2 #include "cmd-io/cmd-save.h"
3 #include "core/asking-player.h"
4 #include "core/scores.h"
5 #include "core/stuff-handler.h"
6 #include "game-option/cheat-options.h"
7 #include "io/input-key-acceptor.h"
8 #include "io/signal-handlers.h"
9 #include "io/uid-checker.h"
10 #include "main/music-definitions-table.h"
11 #include "main/sound-of-music.h"
12 #include "player/process-death.h"
13 #include "save/save.h"
14 #include "term/screen-processor.h"
15 #include "util/angband-files.h"
16 #include "util/int-char-converter.h"
17 #include "view/display-messages.h"
18 #include "view/display-player.h"
19 #include "world/world.h"
20
21 static void clear_floor(player_type *player_ptr)
22 {
23     (void)fd_close(highscore_fd);
24     highscore_fd = -1;
25     clear_saved_floor_files(player_ptr);
26     signals_handle_tstp();
27 }
28
29 static void send_world_score_on_closing(player_type *player_ptr, bool do_send)
30 {
31     if (send_world_score(player_ptr, do_send, update_playtime, display_player))
32         return;
33
34     if (!get_check_strict(
35             player_ptr, _("後でスコアを登録するために待機しますか?", "Stand by for later score registration? "), (CHECK_NO_ESCAPE | CHECK_NO_HISTORY)))
36         return;
37
38     player_ptr->wait_report_score = TRUE;
39     player_ptr->is_dead = FALSE;
40     if (!save_player(player_ptr, SAVE_TYPE_NORMAL))
41         msg_print(_("セーブ失敗!", "death save failed!"));
42 }
43
44 /*!
45  * @brief ゲームクローズ時、プレイヤーが死亡しているかのチェックを行い死亡していないならば、確認キー入力とスコア表示、現フロアの初期化を行う。
46  * @param player_ptr プレイヤー構造体参照ポインタ。
47  * @return 死亡していればTRUE, まだ生きているならば各処理を済ませた上ででFALSE。
48  */
49 static bool check_death(player_type *player_ptr)
50 {
51     if (player_ptr->is_dead)
52         return TRUE;
53
54     do_cmd_save_game(player_ptr, FALSE);
55     prt(_("リターンキーか ESC キーを押して下さい。", "Press Return (or Escape)."), 0, 40);
56     play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_EXIT);
57     if (inkey() != ESCAPE)
58         predict_score(player_ptr);
59
60     clear_floor(player_ptr);
61     return FALSE;
62 }
63
64 /*!
65  * @brief ゲーム終了処理 /
66  * Close up the current game (player may or may not be dead)
67  * @param creature_ptr プレーヤーへの参照ポインタ
68  * @return なし
69  * @details
70  * <pre>
71  * This function is called only from "main.c" and "signals.c".
72  * </pre>
73  */
74 void close_game(player_type *player_ptr)
75 {
76     bool do_send = TRUE;
77     handle_stuff(player_ptr);
78     msg_print(NULL);
79     flush();
80     signals_ignore_tstp();
81
82     current_world_ptr->character_icky = TRUE;
83     char buf[1024];
84     path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");
85     safe_setuid_grab(player_ptr);
86     highscore_fd = fd_open(buf, O_RDWR);
87     safe_setuid_drop();
88
89     if (!check_death(player_ptr))
90         return;
91
92     if (current_world_ptr->total_winner)
93         kingly(player_ptr);
94
95     if (!cheat_save || get_check(_("死んだデータをセーブしますか? ", "Save death? "))) {
96         if (!save_player(player_ptr, SAVE_TYPE_NORMAL))
97             msg_print(_("セーブ失敗!", "death save failed!"));
98     } else
99         do_send = FALSE;
100
101     print_tomb(player_ptr);
102     flush();
103     show_death_info(player_ptr, update_playtime, display_player);
104     term_clear();
105     if (check_score(player_ptr)) {
106         send_world_score_on_closing(player_ptr, do_send);
107         if (!player_ptr->wait_report_score)
108             (void)top_twenty(player_ptr);
109     } else if (highscore_fd >= 0) {
110         display_scores_aux(0, 10, -1, NULL);
111     }
112
113     clear_floor(player_ptr);
114 }