OSDN Git Service

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