OSDN Git Service

Merge pull request #1192 from hengband/feature/3.0.0Alpha26
[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/dungeon.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/monster-race-definition.h"
29 #include "system/system-variables.h"
30 #include "term/screen-processor.h"
31 #include "term/term-color-types.h"
32 #include "time.h"
33 #include "util/angband-files.h"
34 #include "world/world.h"
35 #ifndef WINDOWS
36 #include <dirent.h>
37 #include "util/string-processor.h"
38 #endif
39
40 char *file_read__buf;
41 char *file_read__swp;
42 char *file_read__tmp;
43
44 /*!
45  * @brief 各データファイルを読み取るためのパスを取得する
46  * Find the default paths to all of our important sub-directories.
47  * @param path パス保管先の文字列
48  */
49 void init_file_paths(char *libpath, char *varpath)
50 {
51     char *libtail, *vartail;
52     char buf[1024];
53
54     string_free(ANGBAND_DIR);
55     string_free(ANGBAND_DIR_APEX);
56     string_free(ANGBAND_DIR_BONE);
57     string_free(ANGBAND_DIR_DATA);
58     string_free(ANGBAND_DIR_EDIT);
59     string_free(ANGBAND_DIR_SCRIPT);
60     string_free(ANGBAND_DIR_FILE);
61     string_free(ANGBAND_DIR_HELP);
62     string_free(ANGBAND_DIR_INFO);
63     string_free(ANGBAND_DIR_SAVE);
64     string_free(ANGBAND_DIR_DEBUG_SAVE);
65     string_free(ANGBAND_DIR_USER);
66     string_free(ANGBAND_DIR_XTRA);
67
68     ANGBAND_DIR = string_make(libpath);
69     libtail = libpath + strlen(libpath);
70     vartail = varpath + strlen(varpath);
71     strcpy(vartail, "apex");
72     ANGBAND_DIR_APEX = string_make(varpath);
73     strcpy(vartail, "bone");
74     ANGBAND_DIR_BONE = string_make(varpath);
75     strcpy(vartail, "data");
76     ANGBAND_DIR_DATA = string_make(varpath);
77     strcpy(libtail, "edit");
78     ANGBAND_DIR_EDIT = string_make(libpath);
79     strcpy(libtail, "script");
80     ANGBAND_DIR_SCRIPT = string_make(libpath);
81     strcpy(libtail, "file");
82     ANGBAND_DIR_FILE = string_make(libpath);
83     strcpy(libtail, "help");
84     ANGBAND_DIR_HELP = string_make(libpath);
85     strcpy(libtail, "info");
86     ANGBAND_DIR_INFO = string_make(libpath);
87     strcpy(libtail, "pref");
88     ANGBAND_DIR_PREF = string_make(libpath);
89     strcpy(vartail, "save");
90     ANGBAND_DIR_SAVE = string_make(varpath);
91     path_build(buf, sizeof(buf), ANGBAND_DIR_SAVE, "log");
92     ANGBAND_DIR_DEBUG_SAVE = string_make(buf);
93 #ifdef PRIVATE_USER_PATH
94     path_build(buf, sizeof(buf), PRIVATE_USER_PATH, VERSION_NAME);
95     ANGBAND_DIR_USER = string_make(buf);
96 #else
97     strcpy(vartail, "user");
98     ANGBAND_DIR_USER = string_make(varpath);
99 #endif
100     strcpy(libtail, "xtra");
101     ANGBAND_DIR_XTRA = string_make(libpath);
102
103     time_t now = time(NULL);
104     struct tm *t = localtime(&now);
105     char tmp[128];
106     strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", t);
107     path_build(debug_savefile, sizeof(debug_savefile), ANGBAND_DIR_DEBUG_SAVE, tmp);
108
109 #ifdef WINDOWS
110     struct _finddata_t c_file;
111     intptr_t hFile;
112     char log_file_expr[1024];
113     path_build(log_file_expr, sizeof(log_file_expr), ANGBAND_DIR_DEBUG_SAVE, "*-*");
114
115     if ((hFile = _findfirst(log_file_expr, &c_file)) != -1L) {
116         do {
117             if (((t->tm_yday + 365 - localtime(&c_file.time_write)->tm_yday) % 365) > 7) {
118                 char c_file_fullpath[1024];
119                 path_build(c_file_fullpath, sizeof(c_file_fullpath), ANGBAND_DIR_DEBUG_SAVE, c_file.name);
120                 remove(c_file_fullpath);
121             }
122         } while (_findnext(hFile, &c_file) == 0);
123         _findclose(hFile);
124     }
125 #else
126     {
127         DIR *saves_dir = opendir(ANGBAND_DIR_DEBUG_SAVE);
128
129         if (saves_dir) {
130             struct dirent *next_entry;
131
132             while ((next_entry = readdir(saves_dir))) {
133                 if (angband_strchr(next_entry->d_name, '-')) {
134                     char path[1024];
135                     struct stat next_stat;
136
137                     path_build(path, sizeof(path), ANGBAND_DIR_DEBUG_SAVE, next_entry->d_name);
138                     /*
139                      * Remove if modified more than a week ago,
140                      * 7*24*60*60 seconds.
141                      */
142                     if (stat(path, &next_stat) == 0 &&
143                             difftime(now, next_stat.st_mtime) > 604800) {
144                         remove(path);
145                     }
146                 }
147             }
148             closedir(saves_dir);
149         }
150     }
151 #endif
152 }
153
154 /*!
155  * @brief 画面左下にシステムメッセージを表示する / Take notes on line 23
156  * @param str 初期化中のコンテンツ文字列
157  */
158 static void init_note_term(concptr str)
159 {
160     term_erase(0, 23, 255);
161     term_putstr(20, 23, -1, TERM_WHITE, str);
162     term_fresh();
163 }
164
165 /*!
166  * @brief ゲーム画面無しの時の初期化メッセージ出力
167  * @param str 初期化中のコンテンツ文字列
168  */
169 static void init_note_no_term(concptr str)
170 {
171     /* Don't show initialization message when there is no game terminal. */
172     (void)str;
173 }
174
175 /*!
176  * @brief 全ゲームデータ読み込みのサブルーチン / Explain a broken "lib" folder and quit (see below).
177  * @param なし
178  * @note
179  * <pre>
180  * This function is "messy" because various things
181  * may or may not be initialized, but the "plog()" and "quit()"
182  * functions are "supposed" to work under any conditions.
183  * </pre>
184  */
185 static void init_angband_aux(concptr why)
186 {
187     plog(why);
188     plog(_("'lib'ディレクトリが存在しないか壊れているようです。", "The 'lib' directory is probably missing or broken."));
189     plog(_("ひょっとするとアーカイブが正しく解凍されていないのかもしれません。", "The 'lib' directory is probably missing or broken."));
190     plog(_("該当する'README'ファイルを読んで確認してみて下さい。", "See the 'README' file for more information."));
191     quit(_("致命的なエラー。", "Fatal Error."));
192 }
193
194 /*!
195  * @brief タイトル記述
196  * @param なし
197  */
198 static void put_title(void)
199 {
200     char title[120];
201     put_version(title);
202
203     int col = (80 - strlen(title)) / 2;
204     col = col < 0 ? 0 : col;
205     const int VER_INFO_ROW = 3; //!< タイトル表記(行)
206     prt(title, VER_INFO_ROW, col);
207 }
208
209 /*!
210  * @brief 全ゲームデータ読み込みのメインルーチン /
211  * @param player_ptr プレーヤーへの参照ポインタ
212  * @param no_term TRUEならゲーム画面無しの状態で初期化を行う。
213  *                コマンドラインからスポイラーの出力のみを行う時の使用を想定する。
214  */
215 void init_angband(player_type *player_ptr, bool no_term)
216 {
217     C_MAKE(file_read__buf, FILE_READ_BUFF_SIZE, char);
218     C_MAKE(file_read__swp, FILE_READ_BUFF_SIZE, char);
219     C_MAKE(file_read__tmp, FILE_READ_BUFF_SIZE, char);
220     char buf[1024];
221     path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
222     int fd = fd_open(buf, O_RDONLY);
223     if (fd < 0) {
224         char why[sizeof(buf) + 128];
225         sprintf(why, _("'%s'ファイルにアクセスできません!", "Cannot access the '%s' file!"), buf);
226         init_angband_aux(why);
227     }
228
229     (void)fd_close(fd);
230
231     if (!no_term) {
232         term_clear();
233
234         path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("news_j.txt", "news.txt"));
235         FILE *fp;
236         fp = angband_fopen(buf, "r");
237         if (fp) {
238             int i = 0;
239             while (0 == angband_fgets(fp, buf, sizeof(buf)))
240                 term_putstr(0, i++, -1, TERM_WHITE, buf);
241
242             angband_fclose(fp);
243         }
244
245         term_flush();
246     }
247
248     path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");
249     fd = fd_open(buf, O_RDONLY);
250     BIT_FLAGS file_permission = 0664;
251     if (fd < 0) {
252         safe_setuid_grab(player_ptr);
253         fd = fd_make(buf, file_permission);
254         safe_setuid_drop();
255         if (fd < 0) {
256             char why[sizeof(buf) + 128];
257             sprintf(why, _("'%s'ファイルを作成できません!", "Cannot create the '%s' file!"), buf);
258             init_angband_aux(why);
259         }
260     }
261
262     (void)fd_close(fd);
263     if (!no_term) {
264         put_title();
265     }
266
267     void (*init_note)(concptr) = (no_term ? init_note_no_term : init_note_term);
268
269     init_note(_("[変数を初期化しています...(その他)", "[Initializing values... (misc)]"));
270     if (init_misc(player_ptr))
271         quit(_("その他の変数を初期化できません", "Cannot initialize misc. values"));
272
273     init_note(_("[データの初期化中... (地形)]", "[Initializing arrays... (features)]"));
274     if (init_f_info())
275         quit(_("地形初期化不能", "Cannot initialize features"));
276
277     if (init_feat_variables())
278         quit(_("地形初期化不能", "Cannot initialize features"));
279
280     init_note(_("[データの初期化中... (アイテム)]", "[Initializing arrays... (objects)]"));
281     if (init_k_info())
282         quit(_("アイテム初期化不能", "Cannot initialize objects"));
283
284     init_note(_("[データの初期化中... (伝説のアイテム)]", "[Initializing arrays... (artifacts)]"));
285     if (init_a_info())
286         quit(_("伝説のアイテム初期化不能", "Cannot initialize artifacts"));
287
288     init_note(_("[データの初期化中... (名のあるアイテム)]", "[Initializing arrays... (ego-items)]"));
289     if (init_e_info())
290         quit(_("名のあるアイテム初期化不能", "Cannot initialize ego-items"));
291
292     init_note(_("[データの初期化中... (モンスター)]", "[Initializing arrays... (monsters)]"));
293     if (init_r_info())
294         quit(_("モンスター初期化不能", "Cannot initialize monsters"));
295
296     init_note(_("[データの初期化中... (ダンジョン)]", "[Initializing arrays... (dungeon)]"));
297     if (init_d_info())
298         quit(_("ダンジョン初期化不能", "Cannot initialize dungeon"));
299
300     for (int i = 1; i < current_world_ptr->max_d_idx; i++)
301         if (d_info[i].final_guardian)
302             r_info[d_info[i].final_guardian].flags7 |= RF7_GUARDIAN;
303
304     init_note(_("[データの初期化中... (魔法)]", "[Initializing arrays... (magic)]"));
305     if (init_m_info())
306         quit(_("魔法初期化不能", "Cannot initialize magic"));
307
308     init_note(_("[データの初期化中... (熟練度)]", "[Initializing arrays... (skill)]"));
309     if (init_s_info())
310         quit(_("熟練度初期化不能", "Cannot initialize skill"));
311
312     init_note(_("[配列を初期化しています... (荒野)]", "[Initializing arrays... (wilderness)]"));
313     if (init_wilderness())
314         quit(_("荒野を初期化できません", "Cannot initialize wilderness"));
315
316     init_note(_("[配列を初期化しています... (街)]", "[Initializing arrays... (towns)]"));
317     if (init_towns())
318         quit(_("街を初期化できません", "Cannot initialize towns"));
319
320     init_note(_("[配列を初期化しています... (建物)]", "[Initializing arrays... (buildings)]"));
321     if (init_buildings())
322         quit(_("建物を初期化できません", "Cannot initialize buildings"));
323
324     init_note(_("[配列を初期化しています... (クエスト)]", "[Initializing arrays... (quests)]"));
325     if (init_quests())
326         quit(_("クエストを初期化できません", "Cannot initialize quests"));
327
328     if (init_v_info())
329         quit(_("vault 初期化不能", "Cannot initialize vaults"));
330
331     init_note(_("[データの初期化中... (その他)]", "[Initializing arrays... (other)]"));
332     if (init_other(player_ptr))
333         quit(_("その他のデータ初期化不能", "Cannot initialize other stuff"));
334
335     init_note(_("[データの初期化中... (アロケーション)]", "[Initializing arrays... (alloc)]"));
336     if (init_alloc())
337         quit(_("アロケーション・スタッフ初期化不能", "Cannot initialize alloc stuff"));
338
339     init_note(_("[ユーザー設定ファイルを初期化しています...]", "[Initializing user pref files...]"));
340     strcpy(buf, "pref.prf");
341     process_pref_file(player_ptr, buf);
342     sprintf(buf, "pref-%s.prf", ANGBAND_SYS);
343     process_pref_file(player_ptr, buf);
344     init_note(_("[初期化終了]", "[Initialization complete]"));
345 }