OSDN Git Service

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