OSDN Git Service

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