OSDN Git Service

Merge pull request #2013 from sikabane-works/release/3.0.0Alpha51
[hengbandforosx/hengbandosx.git] / src / load / floor-loader.cpp
1 #include "load/floor-loader.h"
2 #include "floor/floor-generator.h"
3 #include "floor/floor-object.h"
4 #include "floor/floor-save-util.h"
5 #include "game-option/birth-options.h"
6 #include "grid/feature.h"
7 #include "grid/grid.h"
8 #include "io/files-util.h"
9 #include "io/uid-checker.h"
10 #include "load/angband-version-comparer.h"
11 #include "load/item/item-loader-factory.h"
12 #include "load/load-util.h"
13 #include "load/old-feature-types.h"
14 #include "load/monster/monster-loader-factory.h"
15 #include "load/old/item-loader-savefile10.h"
16 #include "load/old/load-v1-5-0.h"
17 #include "load/old/monster-loader-savefile10.h"
18 #include "monster-race/monster-race.h"
19 #include "monster/monster-info.h"
20 #include "monster/monster-list.h"
21 #include "save/floor-writer.h"
22 #include "system/angband-version.h"
23 #include "system/floor-type-definition.h"
24 #include "system/grid-type-definition.h"
25 #include "system/monster-race-definition.h"
26 #include "system/object-type-definition.h"
27 #include "system/player-type-definition.h"
28 #include "util/angband-files.h"
29 #include "world/world-object.h"
30 #include "world/world.h"
31
32 /*!
33  * @brief 保存されたフロアを読み込む / Read the saved floor
34  * @param player_ptr プレイヤーへの参照ポインタ
35  * @param sf_ptr 最後に保存されたフロアへの参照ポインタ
36  * @return info読み込みエラーコード
37  * @details
38  * この関数は、セーブデータの互換性を保つために多くのデータ改変処理を備えている。
39  * 現在確認している処理は以下の通り、
40  * <ul>
41  * <li>1.7.0.2で8bitだったgrid_typeのfeat,mimicのID値を16bitに拡張する処理。</li>
42  * <li>1.7.0.8までに廃止、IDなどを差し替えたクエスト番号を置換する処理。</li>
43  * </ul>
44  * The monsters/objects must be loaded in the same order
45  * that they were stored, since the actual indexes matter.
46  */
47 errr rd_saved_floor(PlayerType *player_ptr, saved_floor_type *sf_ptr)
48 {
49     floor_type *floor_ptr = player_ptr->current_floor_ptr;
50     clear_cave(player_ptr);
51     player_ptr->x = player_ptr->y = 0;
52
53     if (!sf_ptr) {
54         floor_ptr->dun_level = rd_s16b();
55         floor_ptr->base_level = floor_ptr->dun_level;
56     } else {
57         if (rd_s16b() != sf_ptr->floor_id)
58             return 171;
59
60         if (rd_byte() != sf_ptr->savefile_id)
61             return 171;
62
63         if (rd_s16b() != sf_ptr->dun_level)
64             return 171;
65         floor_ptr->dun_level = sf_ptr->dun_level;
66
67         if (rd_s32b() != sf_ptr->last_visit)
68             return 171;
69
70         if (rd_u32b() != sf_ptr->visit_mark)
71             return 171;
72
73         if (rd_s16b() != sf_ptr->upper_floor_id)
74             return 171;
75
76         if (rd_s16b() != sf_ptr->lower_floor_id)
77             return 171;
78     }
79
80     floor_ptr->base_level = rd_s16b();
81     floor_ptr->num_repro = rd_s16b();
82
83     player_ptr->y = rd_u16b();
84
85     player_ptr->x = rd_u16b();
86
87     floor_ptr->height = rd_s16b();
88     floor_ptr->width = rd_s16b();
89
90     player_ptr->feeling = rd_byte();
91
92     auto limit = rd_u16b();
93     std::vector<grid_template_type> templates(limit);
94
95     for (auto &ct_ref : templates) {
96         ct_ref.info = rd_u16b();
97         if (h_older_than(1, 7, 0, 2)) {
98             ct_ref.feat = rd_byte();
99             ct_ref.mimic = rd_byte();
100         } else {
101             ct_ref.feat = rd_s16b();
102             ct_ref.mimic = rd_s16b();
103         }
104
105         ct_ref.special = rd_s16b();
106     }
107
108     POSITION ymax = floor_ptr->height;
109     POSITION xmax = floor_ptr->width;
110     for (POSITION x = 0, y = 0; y < ymax;) {
111         auto count = rd_byte();
112
113         uint16_t id = 0;
114         byte tmp8u;
115         do {
116             tmp8u = rd_byte();
117             id += tmp8u;
118         } while (tmp8u == MAX_UCHAR);
119
120         for (int i = count; i > 0; i--) {
121             grid_type *g_ptr = &floor_ptr->grid_array[y][x];
122             g_ptr->info = templates[id].info;
123             g_ptr->feat = templates[id].feat;
124             g_ptr->mimic = templates[id].mimic;
125             g_ptr->special = templates[id].special;
126
127             if (++x >= xmax) {
128                 x = 0;
129                 if (++y >= ymax)
130                     break;
131             }
132         }
133     }
134
135     /* Quest 18 was removed */
136     if (h_older_than(1, 7, 0, 6) && !vanilla_town) {
137         for (POSITION y = 0; y < ymax; y++) {
138             for (POSITION x = 0; x < xmax; x++) {
139                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
140
141                 if ((g_ptr->special == OLD_QUEST_WATER_CAVE) && !floor_ptr->dun_level) {
142                     if (g_ptr->feat == OLD_FEAT_QUEST_ENTER) {
143                         g_ptr->feat = feat_tree;
144                         g_ptr->special = 0;
145                     } else if (g_ptr->feat == OLD_FEAT_BLDG_1) {
146                         g_ptr->special = lite_town ? QUEST_OLD_CASTLE : QUEST_ROYAL_CRYPT;
147                     }
148                 } else if ((g_ptr->feat == OLD_FEAT_QUEST_EXIT) && (floor_ptr->inside_quest == OLD_QUEST_WATER_CAVE)) {
149                     g_ptr->feat = feat_up_stair;
150                     g_ptr->special = 0;
151                 }
152             }
153         }
154     }
155
156     limit = rd_u16b();
157     if (limit > w_ptr->max_o_idx)
158         return 151;
159
160     auto item_loader = ItemLoaderFactory::create_loader();
161     for (int i = 1; i < limit; i++) {
162         auto o_idx = o_pop(floor_ptr);
163         if (i != o_idx) {
164             return 152;
165         }
166
167         auto &item = floor_ptr->o_list[o_idx];
168         item_loader->rd_item(&item);
169         auto &list = get_o_idx_list_contains(floor_ptr, o_idx);
170         list.add(floor_ptr, o_idx, item.stack_idx);
171     }
172
173     limit = rd_u16b();
174     if (limit > w_ptr->max_m_idx)
175         return 161;
176
177     auto monster_loader = MonsterLoaderFactory::create_loader(player_ptr);
178     for (auto i = 1; i < limit; i++) {
179         auto m_idx = m_pop(floor_ptr);
180         if (i != m_idx) {
181             return 162;
182         }
183
184         auto *m_ptr = &floor_ptr->m_list[m_idx];
185         monster_loader->rd_monster(m_ptr);
186         auto *g_ptr = &floor_ptr->grid_array[m_ptr->fy][m_ptr->fx];
187         g_ptr->m_idx = m_idx;
188         real_r_ptr(m_ptr)->cur_num++;
189     }
190
191     return 0;
192 }
193
194 /*!
195  * @brief 保存フロア読み込みのサブ関数 / Actually load and verify a floor save data
196  * @param player_ptr プレイヤーへの参照ポインタ
197  * @param sf_ptr 保存フロア読み込み先
198  * @return 成功したらtrue
199  */
200 static bool load_floor_aux(PlayerType *player_ptr, saved_floor_type *sf_ptr)
201 {
202     load_xor_byte = 0;
203     strip_bytes(1);
204
205     v_check = 0L;
206     x_check = 0L;
207
208     w_ptr->h_ver_extra = H_VER_EXTRA;
209     w_ptr->h_ver_patch = H_VER_PATCH;
210     w_ptr->h_ver_minor = H_VER_MINOR;
211     w_ptr->h_ver_major = H_VER_MAJOR;
212     loading_savefile_version = SAVEFILE_VERSION;
213
214     if (saved_floor_file_sign != rd_u32b())
215         return false;
216
217     if (rd_saved_floor(player_ptr, sf_ptr))
218         return false;
219
220     auto n_v_check = v_check;
221     if (rd_u32b() != n_v_check)
222         return false;
223
224     auto n_x_check = x_check;
225     if (rd_u32b() != n_x_check)
226         return false;
227     return true;
228 }
229
230 /*!
231  * @brief 一時保存フロア情報を読み込む / Attempt to load the temporarily saved-floor data
232  * @param player_ptr プレイヤーへの参照ポインタ
233  * @param sf_ptr 保存フロア読み込み先
234  * @param mode オプション
235  * @return 成功したらtrue
236  */
237 bool load_floor(PlayerType *player_ptr, saved_floor_type *sf_ptr, BIT_FLAGS mode)
238 {
239     /*
240      * Temporary files are always written in system depended kanji
241      * code.
242      */
243 #ifdef JP
244 #ifdef EUC
245     kanji_code = 2;
246 #endif
247 #ifdef SJIS
248     kanji_code = 3;
249 #endif
250 #else
251     kanji_code = 1;
252 #endif
253
254     FILE *old_fff = nullptr;
255     byte old_xor_byte = 0;
256     uint32_t old_v_check = 0;
257     uint32_t old_x_check = 0;
258     byte old_h_ver_major = 0;
259     byte old_h_ver_minor = 0;
260     byte old_h_ver_patch = 0;
261     byte old_h_ver_extra = 0;
262     uint32_t old_loading_savefile_version = 0;
263     if (mode & SLF_SECOND) {
264         old_fff = loading_savefile;
265         old_xor_byte = load_xor_byte;
266         old_v_check = v_check;
267         old_x_check = x_check;
268         old_h_ver_major = w_ptr->h_ver_major;
269         old_h_ver_minor = w_ptr->h_ver_minor;
270         old_h_ver_patch = w_ptr->h_ver_patch;
271         old_h_ver_extra = w_ptr->h_ver_extra;
272         old_loading_savefile_version = loading_savefile_version;
273     }
274
275     char floor_savefile[sizeof(savefile) + 32];
276     sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
277
278     safe_setuid_grab(player_ptr);
279     loading_savefile = angband_fopen(floor_savefile, "rb");
280     safe_setuid_drop();
281
282     bool is_save_successful = true;
283     if (!loading_savefile)
284         is_save_successful = false;
285
286     if (is_save_successful) {
287         is_save_successful = load_floor_aux(player_ptr, sf_ptr);
288         if (ferror(loading_savefile))
289             is_save_successful = false;
290
291         angband_fclose(loading_savefile);
292         safe_setuid_grab(player_ptr);
293         if (!(mode & SLF_NO_KILL))
294             (void)fd_kill(floor_savefile);
295
296         safe_setuid_drop();
297     }
298
299     if (mode & SLF_SECOND) {
300         loading_savefile = old_fff;
301         load_xor_byte = old_xor_byte;
302         v_check = old_v_check;
303         x_check = old_x_check;
304         w_ptr->h_ver_major = old_h_ver_major;
305         w_ptr->h_ver_minor = old_h_ver_minor;
306         w_ptr->h_ver_patch = old_h_ver_patch;
307         w_ptr->h_ver_extra = old_h_ver_extra;
308         loading_savefile_version = old_loading_savefile_version;
309     }
310
311     byte old_kanji_code = kanji_code;
312     kanji_code = old_kanji_code;
313     return is_save_successful;
314 }