OSDN Git Service

0899d4cfcd7a5f56df8e879ffc5c81d3d430d81c
[hengbandforosx/hengbandosx.git] / src / load / load.cpp
1 /*!
2  * @brief セーブファイル読み込み処理 / Purpose: support for loading savefiles -BEN-
3  * @date 2014/07/07
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6  *
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  */
11
12 #include "load/load.h"
13 #include "core/asking-player.h"
14 #include "dungeon/quest.h"
15 #include "game-option/birth-options.h"
16 #include "io/files-util.h"
17 #include "io/report.h"
18 #include "io/uid-checker.h"
19 #include "load/angband-version-comparer.h"
20 #include "load/dummy-loader.h"
21 #include "load/dungeon-loader.h"
22 #include "load/extra-loader.h"
23 #include "load/info-loader.h"
24 #include "load/inventory-loader.h"
25 #include "load/item-loader.h"
26 #include "load/load-util.h"
27 #include "load/load-v1-5-0.h"
28 #include "load/load-v1-7-0.h"
29 #include "load/load-zangband.h"
30 #include "load/lore-loader.h"
31 #include "load/option-loader.h"
32 #include "load/player-info-loader.h"
33 #include "load/quest-loader.h"
34 #include "load/store-loader.h"
35 #include "load/world-loader.h"
36 #include "player-info/class-info.h"
37 #include "player-info/race-info.h"
38 #include "player/player-personality.h"
39 #include "player/player-sex.h"
40 #include "player/race-info-table.h"
41 #include "system/angband-version.h"
42 #include "system/player-type-definition.h"
43 #include "system/system-variables.h"
44 #include "util/angband-files.h"
45 #include "util/enum-converter.h"
46 #include "view/display-messages.h"
47 #include "world/world.h"
48
49 /*!
50  * @brief 変愚蛮怒 v2.1.3で追加された街とクエストについて読み込む
51  * @param player_ptr プレイヤーへの参照ポインタ
52  * @return エラーコード
53  */
54 static errr load_town_quest(player_type *player_ptr)
55 {
56     if (h_older_than(2, 1, 3))
57         return 0;
58
59     errr load_town_result = load_town();
60     if (load_town_result != 0)
61         return load_town_result;
62
63     uint16_t max_quests_load;
64     byte max_rquests_load;
65     errr load_quest_result = load_quest_info(&max_quests_load, &max_rquests_load);
66     if (load_quest_result != 0)
67         return load_quest_result;
68
69     analyze_quests(player_ptr, max_quests_load, max_rquests_load);
70
71     /* Quest 18 was removed */
72     if (h_older_than(1, 7, 0, 6)) {
73         quest[OLD_QUEST_WATER_CAVE] = {};
74         quest[OLD_QUEST_WATER_CAVE].status = QUEST_STATUS_UNTAKEN;
75     }
76
77     load_wilderness_info(player_ptr);
78     return analyze_wilderness();
79 }
80
81 /*!
82  * @brief 合計のプレイ時間をロードする
83  */
84 static void rd_total_play_time()
85 {
86     if (loading_savefile_version_is_older_than(4))
87         return;
88
89     rd_u32b(&w_ptr->sf_play_time);
90 }
91
92 /*!
93  * @brief 勝利した職業フラグをロードする
94  */
95 static void rd_winner_class()
96 {
97     if (loading_savefile_version_is_older_than(4))
98         return;
99
100     rd_FlagGroup(w_ptr->sf_winner, rd_byte);
101     rd_FlagGroup(w_ptr->sf_retired, rd_byte);
102 }
103
104 static void load_player_world(player_type *player_ptr)
105 {
106     rd_total_play_time();
107     rd_winner_class();
108     rd_base_info(player_ptr);
109     rd_player_info(player_ptr);
110     rd_byte((byte *)&preserve_mode);
111     rd_byte((byte *)&player_ptr->wait_report_score);
112     rd_dummy2();
113     rd_global_configurations(player_ptr);
114     rd_extra(player_ptr);
115
116     if (player_ptr->energy_need < -999)
117         player_ptr->timewalk = true;
118
119     load_note(_("特別情報をロードしました", "Loaded extra information"));
120 }
121
122 static errr load_hp(player_type *player_ptr)
123 {
124     uint16_t tmp16u;
125     rd_u16b(&tmp16u);
126     if (tmp16u > PY_MAX_LEVEL) {
127         load_note(format(_("ヒットポイント配列が大きすぎる(%u)!", "Too many (%u) hitpoint entries!"), tmp16u));
128         return 25;
129     }
130
131     for (int i = 0; i < tmp16u; i++) {
132         int16_t tmp16s;
133         rd_s16b(&tmp16s);
134         player_ptr->player_hp[i] = (HIT_POINT)tmp16s;
135     }
136
137     return 0;
138 }
139
140 static void load_spells(player_type *player_ptr)
141 {
142     rd_u32b(&player_ptr->spell_learned1);
143     rd_u32b(&player_ptr->spell_learned2);
144     rd_u32b(&player_ptr->spell_worked1);
145     rd_u32b(&player_ptr->spell_worked2);
146     rd_u32b(&player_ptr->spell_forgotten1);
147     rd_u32b(&player_ptr->spell_forgotten2);
148
149     if (h_older_than(0, 0, 5))
150         set_zangband_learnt_spells(player_ptr);
151     else
152         rd_s16b(&player_ptr->learned_spells);
153
154     if (h_older_than(0, 0, 6))
155         player_ptr->add_spells = 0;
156     else
157         rd_s16b(&player_ptr->add_spells);
158 }
159
160 static errr verify_checksum()
161 {
162     uint32_t n_v_check = v_check;
163     uint32_t o_v_check;
164     rd_u32b(&o_v_check);
165     if (o_v_check == n_v_check)
166         return 0;
167
168     load_note(_("チェックサムがおかしい", "Invalid checksum"));
169     return 11;
170 }
171
172 static errr verify_encoded_checksum()
173 {
174     uint32_t n_x_check = x_check;
175     uint32_t o_x_check;
176     rd_u32b(&o_x_check);
177     if (o_x_check == n_x_check)
178         return 0;
179
180     load_note(_("エンコードされたチェックサムがおかしい", "Invalid encoded checksum"));
181     return 11;
182 }
183
184 /*!
185  * @brief セーブファイル読み込み処理の実体 / Actually read the savefile
186  * @return エラーコード
187  */
188 static errr exe_reading_savefile(player_type *player_ptr)
189 {
190     rd_version_info();
191     rd_dummy3();
192     rd_system_info();
193     rd_unique_info();
194     errr load_lore_result = load_lore();
195     if (load_lore_result != 0)
196         return load_lore_result;
197
198     errr load_item_result = load_item();
199     if (load_item_result != 0)
200         return load_item_result;
201
202     errr load_town_quest_result = load_town_quest(player_ptr);
203     if (load_town_quest_result != 0)
204         return load_town_quest_result;
205
206     load_note(_("クエスト情報をロードしました", "Loaded Quests"));
207     errr load_artifact_result = load_artifact();
208     if (load_artifact_result != 0)
209         return load_artifact_result;
210
211     load_player_world(player_ptr);
212     errr load_hp_result = load_hp(player_ptr);
213     if (load_hp_result != 0)
214         return load_hp_result;
215
216     sp_ptr = &sex_info[player_ptr->psex];
217     rp_ptr = &race_info[enum2i(player_ptr->prace)];
218     cp_ptr = &class_info[player_ptr->pclass];
219     ap_ptr = &personality_info[player_ptr->ppersonality];
220
221     set_zangband_class(player_ptr);
222     mp_ptr = &m_info[player_ptr->pclass];
223
224     load_spells(player_ptr);
225     if (player_ptr->pclass == CLASS_MINDCRAFTER)
226         player_ptr->add_spells = 0;
227
228     errr load_inventory_result = load_inventory(player_ptr);
229     if (load_inventory_result != 0)
230         return load_inventory_result;
231
232     errr load_store_result = load_store(player_ptr);
233     if (load_store_result != 0)
234         return load_store_result;
235
236     rd_s16b(&player_ptr->pet_follow_distance);
237     if (h_older_than(0, 4, 10))
238         set_zangband_pet(player_ptr);
239     else
240         rd_u16b(&player_ptr->pet_extra_flags);
241
242     if (!h_older_than(1, 0, 9)) {
243         std::vector<char> buf(SCREEN_BUF_MAX_SIZE);
244         rd_string(buf.data(), SCREEN_BUF_MAX_SIZE);
245         if (buf[0])
246             screen_dump = string_make(buf.data());
247     }
248
249     errr restore_dungeon_result = restore_dungeon(player_ptr);
250     if (restore_dungeon_result != 0)
251         return restore_dungeon_result;
252
253     if (h_older_than(1, 7, 0, 6))
254         remove_water_cave(player_ptr);
255
256     errr checksum_result = verify_checksum();
257     if (checksum_result != 0)
258         return checksum_result;
259
260     return verify_encoded_checksum();
261 }
262
263 /*!
264  * @brief セーブファイル読み込み処理 (UIDチェック等含む) / Reading the savefile (including UID check)
265  * @param player_ptr プレイヤーへの参照ポインタ
266  * @return エラーコード
267  */
268 static errr rd_savefile(player_type *player_ptr)
269 {
270     safe_setuid_grab(player_ptr);
271     loading_savefile = angband_fopen(savefile, "rb");
272     safe_setuid_drop();
273     if (!loading_savefile)
274         return -1;
275
276     errr err = exe_reading_savefile(player_ptr);
277     if (ferror(loading_savefile))
278         err = -1;
279
280     angband_fclose(loading_savefile);
281     return err;
282 }
283
284 /**
285  * @brief セーブデータから引き継いでプレイできるかどうか調べる
286  *
287  * @param player_ptr プレイヤーへの参照ポインタ
288  * @return 引き継ぎ可能ならtrue、そうでなければfalseを返す
289  */
290 static bool can_takeover_savefile(const player_type *player_ptr)
291 {
292     if (loading_savefile_version_is_older_than(8) && player_ptr->pclass == CLASS_SMITH) {
293         return false;
294     }
295
296     return true;
297 }
298
299 /*!
300  * @brief セーブデータ読み込みのメインルーチン /
301  * Attempt to Load a "savefile"
302  * @param player_ptr プレイヤーへの参照ポインタ
303  * @param new_game セーブデータの新規作成が必要か否か
304  * @return セーブデータが読み込めればtrue
305  */
306 bool load_savedata(player_type *player_ptr, bool *new_game)
307 {
308     concptr what = "generic";
309     w_ptr->game_turn = 0;
310     player_ptr->is_dead = false;
311     if (!savefile[0])
312         return true;
313
314 #ifndef WINDOWS
315     if (access(savefile, 0) < 0) {
316         msg_print(_("セーブファイルがありません。", "Savefile does not exist."));
317         msg_print(nullptr);
318         *new_game = true;
319         return true;
320     }
321 #endif
322
323     bool err = false;
324     int fd = -1;
325     byte fake_ver[4];
326     if (!err) {
327         fd = fd_open(savefile, O_RDONLY);
328         if (fd < 0)
329             err = true;
330
331         if (err)
332             what = _("セーブファイルを開けません", "Cannot open savefile");
333     }
334
335     if (!err) {
336         if (fd_read(fd, (char *)(fake_ver), 4))
337             err = true;
338
339         if (err)
340             what = _("セーブファイルを読めません", "Cannot read savefile");
341
342         (void)fd_close(fd);
343     }
344
345     if (!err) {
346         if (fake_ver[0] < FAKE_VER_PLUS) {
347             what = _("セーブデータが古すぎます", "Savefile version is too old");
348             err = true;
349         }
350     }
351
352     if (err) {
353         msg_format("%s: %s", what, savefile);
354         msg_print(nullptr);
355         return false;
356     }
357
358     w_ptr->sf_extra = fake_ver[3];
359
360     if (!err) {
361         term_clear();
362         if (rd_savefile(player_ptr))
363             err = true;
364         if (err)
365             what = _("セーブファイルを解析出来ません。", "Cannot parse savefile");
366     }
367
368     if (!err) {
369         if (!w_ptr->game_turn)
370             err = true;
371
372         if (err)
373             what = _("セーブファイルが壊れています", "Broken savefile");
374     }
375
376     if (err) {
377         msg_format(_("エラー(%s)がバージョン%d.%d.%d.%d 用セーブファイル読み込み中に発生。", "Error (%s) reading %d.%d.%d.% savefile."), what,
378             w_ptr->h_ver_major, w_ptr->h_ver_minor, w_ptr->h_ver_patch, w_ptr->h_ver_extra);
379
380         msg_print(nullptr);
381         return false;
382     }
383
384     if (!can_takeover_savefile(player_ptr)) {
385         msg_format(_("このセーブデータの続きをプレイすることはできません。", "You can't play the rest of the game from this save data."));
386         msg_print(nullptr);
387         if (!get_check(_("最初からプレイを始めますか?(モンスターの思い出は引き継がれます)",
388                 "Play from the beginning? (Monster recalls will be inherited.) "))) {
389             msg_format(_("ゲームを終了します。", "Exit the game."));
390             msg_print(nullptr);
391             return false;
392         }
393         player_ptr->is_dead = true;
394         player_ptr->wait_report_score = false;
395     }
396
397     if (player_ptr->is_dead) {
398         *new_game = true;
399         player_ptr->is_dead = false;
400         w_ptr->sf_lives++;
401         return true;
402     }
403
404     w_ptr->character_loaded = true;
405     uint32_t tmp = counts_read(player_ptr, 2);
406     if (tmp > player_ptr->count)
407         player_ptr->count = tmp;
408
409     if (counts_read(player_ptr, 0) > w_ptr->play_time || counts_read(player_ptr, 1) == w_ptr->play_time)
410         counts_write(player_ptr, 2, ++player_ptr->count);
411
412     counts_write(player_ptr, 1, w_ptr->play_time);
413     return true;
414 }