OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / main / angband-initializer.cpp
1 /*!
2  * @file angband-initializer.cpp
3  * @brief 変愚蛮怒のシステム初期化
4  * @date 2014/01/28
5  * @author
6  * <pre>
7  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8  * This software may be copied and distributed for educational, research,
9  * and not for profit purposes provided that this copyright and statement
10  * are included in all such copies.  Other copyrights may also apply.
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  * </pre>
13  */
14
15 #include "main/angband-initializer.h"
16 #include "dungeon/quest.h"
17 #include "floor/wild.h"
18 #include "info-reader/feature-reader.h"
19 #include "io/files-util.h"
20 #include "io/read-pref-file.h"
21 #include "io/uid-checker.h"
22 #include "main/game-data-initializer.h"
23 #include "main/info-initializer.h"
24 #include "market/building-initializer.h"
25 #include "monster-race/monster-race.h"
26 #include "monster-race/race-flags7.h"
27 #include "system/angband-version.h"
28 #include "system/dungeon-info.h"
29 #include "system/monster-race-info.h"
30 #include "system/system-variables.h"
31 #include "term/gameterm.h"
32 #include "term/screen-processor.h"
33 #include "term/term-color-types.h"
34 #include "time.h"
35 #include "util/angband-files.h"
36 #include "world/world.h"
37 #include <chrono>
38
39 /*!
40  * @brief 古いデバッグ用セーブファイルを削除する
41  *
42  * 最終更新日時が現在時刻より7日以前のデバッグ用セーブファイルを削除する。
43  * デバッグ用セーブファイルは、ANGBAND_DIR_DEBUG_SAVEディレクトリにある、
44  * ファイル名に '-' を含むファイルであることを想定する。
45  */
46 static void remove_old_debug_savefiles()
47 {
48     namespace fs = std::filesystem;
49     constexpr auto remove_threshold_days = std::chrono::days(7);
50     const auto now = fs::file_time_type::clock::now();
51
52     // アクセスエラーが発生した場合に例外が送出されないようにするため
53     // 例外を送出せず引数でエラーコードを返すオーバーロードを使用する。
54     // アクセスエラーが発生した場合は単に無視し、エラーコードの確認は行わない。
55     std::error_code ec;
56
57     for (const auto &entry : fs::directory_iterator(ANGBAND_DIR_DEBUG_SAVE, ec)) {
58         const auto &path = entry.path();
59         if (path.filename().string().find('-') == std::string::npos) {
60             continue;
61         }
62
63         const auto savefile_timestamp = fs::last_write_time(path);
64         const auto elapsed_days = std::chrono::duration_cast<std::chrono::days>(now - savefile_timestamp);
65         if (elapsed_days >= remove_threshold_days) {
66             fs::remove(path, ec);
67         }
68     }
69 }
70
71 /*!
72  * @brief 各データファイルを読み取るためのパスを取得する.
73  * @param libpath 各PCのインストール環境における"lib/" を表す絶対パス
74  */
75 void init_file_paths(const std::filesystem::path &libpath)
76 {
77     ANGBAND_DIR = std::filesystem::path(libpath);
78     ANGBAND_DIR_APEX = std::filesystem::path(libpath).append("apex");
79     ANGBAND_DIR_BONE = std::filesystem::path(libpath).append("bone");
80     ANGBAND_DIR_DATA = std::filesystem::path(libpath).append("data");
81     ANGBAND_DIR_EDIT = std::filesystem::path(libpath).append("edit");
82     ANGBAND_DIR_SCRIPT = std::filesystem::path(libpath).append("script");
83     ANGBAND_DIR_FILE = std::filesystem::path(libpath).append("file");
84     ANGBAND_DIR_HELP = std::filesystem::path(libpath).append("help");
85     ANGBAND_DIR_INFO = std::filesystem::path(libpath).append("info");
86     ANGBAND_DIR_PREF = std::filesystem::path(libpath).append("pref");
87     ANGBAND_DIR_SAVE = std::filesystem::path(libpath).append("save");
88     ANGBAND_DIR_DEBUG_SAVE = std::filesystem::path(ANGBAND_DIR_SAVE).append("log");
89 #ifdef PRIVATE_USER_PATH
90     ANGBAND_DIR_USER = std::filesystem::path(PRIVATE_USER_PATH).append(VARIANT_NAME);
91 #else
92     ANGBAND_DIR_USER = std::filesystem::path(libpath).append("user");
93 #endif
94     ANGBAND_DIR_XTRA = std::filesystem::path(libpath).append("xtra");
95
96     time_t now = time(nullptr);
97     struct tm *t = localtime(&now);
98     char tmp[128];
99     strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", t);
100     debug_savefile = path_build(ANGBAND_DIR_DEBUG_SAVE, tmp);
101     remove_old_debug_savefiles();
102 }
103
104 /*!
105  * @brief 画面左下にシステムメッセージを表示する / Take notes on line 23
106  * @param str 初期化中のコンテンツ文字列
107  */
108 static void init_note_term(concptr str)
109 {
110     term_erase(0, 23);
111     term_putstr(20, 23, -1, TERM_WHITE, str);
112     term_fresh();
113 }
114
115 /*!
116  * @brief ゲーム画面無しの時の初期化メッセージ出力
117  * @param str 初期化中のコンテンツ文字列
118  */
119 static void init_note_no_term(concptr str)
120 {
121     /* Don't show initialization message when there is no game terminal. */
122     (void)str;
123 }
124
125 /*!
126  * @brief 全ゲームデータ読み込みのサブルーチン / Explain a broken "lib" folder and quit (see below).
127  * @param なし
128  * @note
129  * <pre>
130  * This function is "messy" because various things
131  * may or may not be initialized, but the "plog()" and "quit()"
132  * functions are "supposed" to work under any conditions.
133  * </pre>
134  */
135 static void init_angband_aux(const std::string &why)
136 {
137     plog(why.data());
138     plog(_("'lib'ディレクトリが存在しないか壊れているようです。", "The 'lib' directory is probably missing or broken."));
139     plog(_("ひょっとするとアーカイブが正しく解凍されていないのかもしれません。", "The 'lib' directory is probably missing or broken."));
140     plog(_("該当する'README'ファイルを読んで確認してみて下さい。", "See the 'README' file for more information."));
141     quit(_("致命的なエラー。", "Fatal Error."));
142 }
143
144 /*!
145  * @brief タイトル記述
146  * @param なし
147  */
148 static void put_title()
149 {
150     const auto title = get_version();
151
152     auto col = (title.length() <= MAIN_TERM_MIN_COLS) ? (MAIN_TERM_MIN_COLS - title.length()) / 2 : 0;
153     constexpr auto VER_INFO_ROW = 3; //!< タイトル表記(行)
154     prt(title, VER_INFO_ROW, col);
155 }
156
157 /*!
158  * @brief 全ゲームデータ読み込みのメインルーチン /
159  * @param player_ptr プレイヤーへの参照ポインタ
160  * @param no_term TRUEならゲーム画面無しの状態で初期化を行う。
161  *                コマンドラインからスポイラーの出力のみを行う時の使用を想定する。
162  */
163 void init_angband(PlayerType *player_ptr, bool no_term)
164 {
165     const auto &path_news = path_build(ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
166     auto fd = fd_open(path_news, O_RDONLY);
167     if (fd < 0) {
168         std::string why = _("'", "Cannot access the '");
169         why.append(path_news.string());
170         why.append(_("'ファイルにアクセスできません!", "' file!"));
171         init_angband_aux(why);
172     }
173
174     (void)fd_close(fd);
175     if (!no_term) {
176         term_clear();
177         auto *fp = angband_fopen(path_news, FileOpenMode::READ);
178         if (fp) {
179             int i = 0;
180             char buf[1024]{};
181             while (0 == angband_fgets(fp, buf, sizeof(buf))) {
182                 term_putstr(0, i++, -1, TERM_WHITE, buf);
183             }
184
185             angband_fclose(fp);
186         }
187
188         term_flush();
189     }
190
191     const auto &path_score = path_build(ANGBAND_DIR_APEX, "scores.raw");
192     fd = fd_open(path_score, O_RDONLY);
193     if (fd < 0) {
194         safe_setuid_grab();
195         fd = fd_make(path_score, true);
196         safe_setuid_drop();
197         if (fd < 0) {
198             const auto &filename_score = path_score.string();
199             std::string why = _("'", "Cannot create the '");
200             why.append(filename_score);
201             why.append(_("'ファイルを作成できません!", "' file!"));
202             init_angband_aux(why);
203         }
204     }
205
206     (void)fd_close(fd);
207     if (!no_term) {
208         put_title();
209     }
210
211     void (*init_note)(concptr) = (no_term ? init_note_no_term : init_note_term);
212
213     init_note(_("[データの初期化中... (地形)]", "[Initializing arrays... (features)]"));
214     if (init_terrains_info()) {
215         quit(_("地形初期化不能", "Cannot initialize features"));
216     }
217
218     if (init_feat_variables()) {
219         quit(_("地形初期化不能", "Cannot initialize features"));
220     }
221
222     init_note(_("[データの初期化中... (アイテム)]", "[Initializing arrays... (objects)]"));
223     if (init_baseitems_info()) {
224         quit(_("アイテム初期化不能", "Cannot initialize objects"));
225     }
226
227     init_note(_("[データの初期化中... (伝説のアイテム)]", "[Initializing arrays... (artifacts)]"));
228     if (init_artifacts_info()) {
229         quit(_("伝説のアイテム初期化不能", "Cannot initialize artifacts"));
230     }
231
232     init_note(_("[データの初期化中... (名のあるアイテム)]", "[Initializing arrays... (ego-items)]"));
233     if (init_egos_info()) {
234         quit(_("名のあるアイテム初期化不能", "Cannot initialize ego-items"));
235     }
236
237     init_note(_("[データの初期化中... (モンスター)]", "[Initializing arrays... (monsters)]"));
238     if (init_monster_race_definitions()) {
239         quit(_("モンスター初期化不能", "Cannot initialize monsters"));
240     }
241
242     init_note(_("[データの初期化中... (ダンジョン)]", "[Initializing arrays... (dungeon)]"));
243     if (init_dungeons_info()) {
244         quit(_("ダンジョン初期化不能", "Cannot initialize dungeon"));
245     }
246
247     for (const auto &d_ref : dungeons_info) {
248         if (d_ref.idx > 0 && MonsterRace(d_ref.final_guardian).is_valid()) {
249             monraces_info[d_ref.final_guardian].misc_flags.set(MonsterMiscType::GUARDIAN);
250         }
251     }
252
253     init_note(_("[データの初期化中... (魔法)]", "[Initializing arrays... (magic)]"));
254     if (init_class_magics_info()) {
255         quit(_("魔法初期化不能", "Cannot initialize magic"));
256     }
257
258     init_note(_("[データの初期化中... (熟練度)]", "[Initializing arrays... (skill)]"));
259     if (init_class_skills_info()) {
260         quit(_("熟練度初期化不能", "Cannot initialize skill"));
261     }
262
263     init_note(_("[配列を初期化しています... (荒野)]", "[Initializing arrays... (wilderness)]"));
264     if (!init_wilderness()) {
265         quit(_("荒野を初期化できません", "Cannot initialize wilderness"));
266     }
267
268     init_note(_("[配列を初期化しています... (街)]", "[Initializing arrays... (towns)]"));
269     init_towns();
270
271     init_note(_("[配列を初期化しています... (建物)]", "[Initializing arrays... (buildings)]"));
272     init_buildings();
273
274     init_note(_("[配列を初期化しています... (クエスト)]", "[Initializing arrays... (quests)]"));
275     QuestList::get_instance().initialize();
276     if (init_vaults_info()) {
277         quit(_("vault 初期化不能", "Cannot initialize vaults"));
278     }
279
280     init_note(_("[データの初期化中... (その他)]", "[Initializing arrays... (other)]"));
281     init_other(player_ptr);
282     init_note(_("[データの初期化中... (モンスターアロケーション)]", "[Initializing arrays... (monsters alloc)]"));
283     init_monsters_alloc();
284     init_note(_("[データの初期化中... (アイテムアロケーション)]", "[Initializing arrays... (items alloc)]"));
285     init_items_alloc();
286     init_note(_("[ユーザー設定ファイルを初期化しています...]", "[Initializing user pref files...]"));
287     process_pref_file(player_ptr, "pref.prf");
288     process_pref_file(player_ptr, std::string("pref-").append(ANGBAND_SYS).append(".prf"));
289     init_note(_("[初期化終了]", "[Initialization complete]"));
290 }