3 * @brief セーブファイル書き込み処理 / Purpose: interact with savefiles
7 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8 * This software may be copied and distributed for educational, research,
9 * and not for profit purposes provided that this copyright and statement
10 * are included in all such copies. Other copyrights may also apply.
14 #include "save/save.h"
15 #include "birth/quick-start.h"
16 #include "cmd-building/cmd-building.h"
17 #include "core/player-update-types.h"
18 #include "dungeon/dungeon.h"
19 #include "dungeon/quest.h"
20 #include "floor/floor-events.h"
21 #include "floor/floor-town.h"
22 #include "floor/floor.h"
23 #include "floor/wild.h"
24 #include "game-option/birth-options.h"
25 #include "game-option/cheat-options.h"
26 #include "game-option/option-flags.h"
27 #include "game-option/option-types-table.h"
28 #include "game-option/runtime-arguments.h"
29 #include "game-option/special-options.h"
30 #include "game-option/text-display-options.h"
31 #include "grid/grid.h"
32 #include "inventory/inventory-slot-types.h"
33 #include "io/report.h"
34 #include "io/uid-checker.h"
35 #include "load/floor-loader.h"
36 #include "load/load.h"
37 #include "load/savedata-flag-types.h"
38 #include "monster-race/monster-race.h"
39 #include "monster/monster-compaction.h"
40 #include "monster/monster-info.h"
41 #include "monster/monster-status.h"
42 #include "object/object-kind.h"
43 #include "save/item-writer.h"
44 #include "save/monster-writer.h"
45 #include "save/save-util.h"
46 #include "store/store-util.h"
47 #include "store/store.h"
48 #include "system/angband-version.h"
49 #include "system/artifact-type-definition.h"
50 #include "system/floor-type-definition.h"
51 #include "util/angband-files.h"
52 #include "util/quarks.h"
53 #include "util/sort.h"
54 #include "view/display-messages.h"
55 #include "world/world.h"
58 * @brief その他のゲーム情報を書き込む(実質はアイテムの鑑定情報のみ) / Write an "xtra" record
59 * @param k_idx ベースアイテムのID
62 static void wr_xtra(KIND_OBJECT_IDX k_idx)
66 object_kind *k_ptr = &k_info[k_idx];
77 * @brief セーブデータに店舗情報を書き込む / Write a "store" record
78 * @param store_ptr 店舗情報の参照ポインタ
81 static void wr_store(store_type *store_ptr)
83 /* Save the "open" counter */
84 wr_u32b(store_ptr->store_open);
86 /* Save the "insults" */
87 wr_s16b(store_ptr->insult_cur);
89 /* Save the current owner */
90 wr_byte(store_ptr->owner);
92 /* Save the stock size */
93 wr_s16b(store_ptr->stock_num);
95 /* Save the "haggle" info */
96 wr_s16b(store_ptr->good_buy);
97 wr_s16b(store_ptr->bad_buy);
99 wr_s32b(store_ptr->last_visit);
102 for (int j = 0; j < store_ptr->stock_num; j++) {
103 /* Save each item in stock */
104 wr_item(&store_ptr->stock[j]);
109 * @brief セーブデータに乱数情報を書き込む / Write RNG state
112 static errr wr_randomizer(void)
117 for (int i = 0; i < RAND_DEG; i++) {
118 wr_u32b(Rand_state[i]);
125 * @brief ゲームオプション情報を書き込む / Write the "options"
128 static void wr_options(void)
130 for (int i = 0; i < 4; i++)
133 /*** Special options ***/
134 /* Write "delay_factor" */
135 wr_byte(delay_factor);
137 /* Write "hitpoint_warn" */
138 wr_byte(hitpoint_warn);
140 /* Write "mana_warn" */
143 /*** Cheating options ***/
146 if (current_world_ptr->wizard)
168 if (cheat_diary_output)
176 wr_s16b(autosave_freq);
178 /*** Extract options ***/
179 /* Analyze the options */
180 for (int i = 0; option_info[i].o_desc; i++) {
181 int os = option_info[i].o_set;
182 int ob = option_info[i].o_bit;
184 /* Process real entries */
185 if (!option_info[i].o_var)
188 if (*option_info[i].o_var) {
189 option_flag[os] |= (1L << ob);
191 option_flag[os] &= ~(1L << ob);
195 /*** Normal options ***/
197 for (int i = 0; i < 8; i++)
198 wr_u32b(option_flag[i]);
201 for (int i = 0; i < 8; i++)
202 wr_u32b(option_mask[i]);
204 /*** Window options ***/
206 for (int i = 0; i < 8; i++)
207 wr_u32b(window_flag[i]);
210 for (int i = 0; i < 8; i++)
211 wr_u32b(window_mask[i]);
215 * @brief ダミー情報スキップを書き込む / Hack -- Write the "ghost" info
218 static void wr_ghost(void)
220 wr_string(_("不正なゴースト", "Broken Ghost"));
222 /* Hack -- stupid data */
223 for (int i = 0; i < 60; i++)
228 * @brief クイック・スタート情報を書き込む / Save quick start data
231 static void save_quick_start(void)
233 wr_byte(previous_char.psex);
234 wr_byte((byte)previous_char.prace);
235 wr_byte((byte)previous_char.pclass);
236 wr_byte((byte)previous_char.pseikaku);
237 wr_byte((byte)previous_char.realm1);
238 wr_byte((byte)previous_char.realm2);
240 wr_s16b(previous_char.age);
241 wr_s16b(previous_char.ht);
242 wr_s16b(previous_char.wt);
243 wr_s16b(previous_char.sc);
244 wr_s32b(previous_char.au);
246 for (int i = 0; i < A_MAX; i++)
247 wr_s16b(previous_char.stat_max[i]);
248 for (int i = 0; i < A_MAX; i++)
249 wr_s16b(previous_char.stat_max_max[i]);
251 for (int i = 0; i < PY_MAX_LEVEL; i++)
252 wr_s16b((s16b)previous_char.player_hp[i]);
254 wr_s16b(previous_char.chaos_patron);
256 for (int i = 0; i < 8; i++)
257 wr_s16b(previous_char.vir_types[i]);
259 for (int i = 0; i < 4; i++)
260 wr_string(previous_char.history[i]);
262 /* UNUSED : Was number of random quests */
265 /* No quick start after using debug mode or cheat options */
266 if (current_world_ptr->noscore)
267 previous_char.quick_ok = FALSE;
269 wr_byte((byte)previous_char.quick_ok);
273 * @brief その他の情報を書き込む / Write some "extra" info
276 static void wr_extra(player_type *creature_ptr)
278 wr_string(creature_ptr->name);
279 wr_string(creature_ptr->died_from);
280 wr_string(creature_ptr->last_message ? creature_ptr->last_message : "");
284 for (int i = 0; i < 4; i++) {
285 wr_string(creature_ptr->history[i]);
288 /* Race/Class/Gender/Spells */
289 wr_byte((byte)creature_ptr->prace);
290 wr_byte((byte)creature_ptr->pclass);
291 wr_byte((byte)creature_ptr->pseikaku);
292 wr_byte((byte)creature_ptr->psex);
293 wr_byte((byte)creature_ptr->realm1);
294 wr_byte((byte)creature_ptr->realm2);
297 wr_byte((byte)creature_ptr->hitdie);
298 wr_u16b(creature_ptr->expfact);
300 wr_s16b(creature_ptr->age);
301 wr_s16b(creature_ptr->ht);
302 wr_s16b(creature_ptr->wt);
304 /* Dump the stats (maximum and current) */
305 for (int i = 0; i < A_MAX; ++i)
306 wr_s16b(creature_ptr->stat_max[i]);
307 for (int i = 0; i < A_MAX; ++i)
308 wr_s16b(creature_ptr->stat_max_max[i]);
309 for (int i = 0; i < A_MAX; ++i)
310 wr_s16b(creature_ptr->stat_cur[i]);
312 /* Ignore the transient stats */
313 for (int i = 0; i < 12; ++i)
316 wr_u32b(creature_ptr->au);
318 wr_u32b(creature_ptr->max_exp);
319 wr_u32b(creature_ptr->max_max_exp);
320 wr_u32b(creature_ptr->exp);
321 wr_u32b(creature_ptr->exp_frac);
322 wr_s16b(creature_ptr->lev);
324 for (int i = 0; i < 64; i++)
325 wr_s16b(creature_ptr->spell_exp[i]);
326 for (int i = 0; i < 5; i++)
327 for (int j = 0; j < 64; j++)
328 wr_s16b(creature_ptr->weapon_exp[i][j]);
330 for (int i = 0; i < GINOU_MAX; i++)
331 wr_s16b(creature_ptr->skill_exp[i]);
332 for (int i = 0; i < MAX_SPELLS; i++)
333 wr_s32b(creature_ptr->magic_num1[i]);
334 for (int i = 0; i < MAX_SPELLS; i++)
335 wr_byte(creature_ptr->magic_num2[i]);
337 wr_byte((byte)creature_ptr->start_race);
338 wr_s32b(creature_ptr->old_race1);
339 wr_s32b(creature_ptr->old_race2);
340 wr_s16b(creature_ptr->old_realm);
342 for (int i = 0; i < MAX_MANE; i++) {
343 wr_s16b((s16b)creature_ptr->mane_spell[i]);
344 wr_s16b((s16b)creature_ptr->mane_dam[i]);
347 wr_s16b(creature_ptr->mane_num);
349 for (int i = 0; i < MAX_BOUNTY; i++) {
350 wr_s16b(current_world_ptr->bounty_r_idx[i]);
353 for (int i = 0; i < 4; i++) {
354 wr_s16b(battle_mon[i]);
355 wr_u32b(mon_odds[i]);
358 wr_s16b(creature_ptr->town_num); /* -KMW- */
360 /* Write arena and rewards information -KMW- */
361 wr_s16b(creature_ptr->arena_number);
362 wr_s16b(creature_ptr->current_floor_ptr->inside_arena);
363 wr_s16b(creature_ptr->current_floor_ptr->inside_quest);
364 wr_s16b(creature_ptr->phase_out);
365 wr_byte(creature_ptr->exit_bldg);
366 wr_byte(0); /* Unused */
368 wr_s16b((s16b)creature_ptr->oldpx);
369 wr_s16b((s16b)creature_ptr->oldpy);
371 /* Was number of creature_ptr->rewards[] */
374 wr_s32b(creature_ptr->mhp);
375 wr_s32b(creature_ptr->chp);
376 wr_u32b(creature_ptr->chp_frac);
378 wr_s32b(creature_ptr->msp);
379 wr_s32b(creature_ptr->csp);
380 wr_u32b(creature_ptr->csp_frac);
382 /* Max Player and Dungeon Levels */
383 wr_s16b(creature_ptr->max_plv);
384 byte tmp8u = (byte)current_world_ptr->max_d_idx;
386 for (int i = 0; i < tmp8u; i++)
387 wr_s16b((s16b)max_dlv[i]);
394 wr_s16b(creature_ptr->sc);
395 wr_s16b(creature_ptr->concent);
397 wr_s16b(0); /* old "rest" */
398 wr_s16b(creature_ptr->blind);
399 wr_s16b(creature_ptr->paralyzed);
400 wr_s16b(creature_ptr->confused);
401 wr_s16b(creature_ptr->food);
402 wr_s16b(0); /* old "food_digested" */
403 wr_s16b(0); /* old "protection" */
404 wr_s16b(creature_ptr->energy_need);
405 wr_s16b(creature_ptr->enchant_energy_need);
406 wr_s16b(creature_ptr->fast);
407 wr_s16b(creature_ptr->slow);
408 wr_s16b(creature_ptr->afraid);
409 wr_s16b(creature_ptr->cut);
410 wr_s16b(creature_ptr->stun);
411 wr_s16b(creature_ptr->poisoned);
412 wr_s16b(creature_ptr->image);
413 wr_s16b(creature_ptr->protevil);
414 wr_s16b(creature_ptr->invuln);
415 wr_s16b(creature_ptr->ult_res);
416 wr_s16b(creature_ptr->hero);
417 wr_s16b(creature_ptr->shero);
418 wr_s16b(creature_ptr->shield);
419 wr_s16b(creature_ptr->blessed);
420 wr_s16b(creature_ptr->tim_invis);
421 wr_s16b(creature_ptr->word_recall);
422 wr_s16b(creature_ptr->recall_dungeon);
423 wr_s16b(creature_ptr->alter_reality);
424 wr_s16b(creature_ptr->see_infra);
425 wr_s16b(creature_ptr->tim_infra);
426 wr_s16b(creature_ptr->oppose_fire);
427 wr_s16b(creature_ptr->oppose_cold);
428 wr_s16b(creature_ptr->oppose_acid);
429 wr_s16b(creature_ptr->oppose_elec);
430 wr_s16b(creature_ptr->oppose_pois);
431 wr_s16b(creature_ptr->tsuyoshi);
432 wr_s16b(creature_ptr->tim_esp);
433 wr_s16b(creature_ptr->wraith_form);
434 wr_s16b(creature_ptr->resist_magic);
435 wr_s16b(creature_ptr->tim_regen);
436 wr_s16b(creature_ptr->tim_pass_wall);
437 wr_s16b(creature_ptr->tim_stealth);
438 wr_s16b(creature_ptr->tim_levitation);
439 wr_s16b(creature_ptr->tim_sh_touki);
440 wr_s16b(creature_ptr->lightspeed);
441 wr_s16b(creature_ptr->tsubureru);
442 wr_s16b(creature_ptr->magicdef);
443 wr_s16b(creature_ptr->tim_res_nether);
444 wr_s16b(creature_ptr->tim_res_time);
445 wr_byte((byte)creature_ptr->mimic_form);
446 wr_s16b(creature_ptr->tim_mimic);
447 wr_s16b(creature_ptr->tim_sh_fire);
448 wr_s16b(creature_ptr->tim_sh_holy);
449 wr_s16b(creature_ptr->tim_eyeeye);
452 wr_s16b(creature_ptr->tim_reflect);
453 wr_s16b(creature_ptr->multishadow);
454 wr_s16b(creature_ptr->dustrobe);
456 wr_s16b(creature_ptr->chaos_patron);
457 wr_u32b(creature_ptr->muta1);
458 wr_u32b(creature_ptr->muta2);
459 wr_u32b(creature_ptr->muta3);
461 for (int i = 0; i < 8; i++)
462 wr_s16b(creature_ptr->virtues[i]);
463 for (int i = 0; i < 8; i++)
464 wr_s16b(creature_ptr->vir_types[i]);
466 wr_s16b(creature_ptr->ele_attack);
467 wr_u32b(creature_ptr->special_attack);
468 wr_s16b(creature_ptr->ele_immune);
469 wr_u32b(creature_ptr->special_defense);
470 wr_byte(creature_ptr->knowledge);
471 wr_byte(creature_ptr->autopick_autoregister);
473 wr_byte((byte)creature_ptr->action);
475 wr_byte(preserve_mode);
476 wr_byte(creature_ptr->wait_report_score);
479 for (int i = 0; i < 12; i++)
482 /* Ignore some flags */
487 /* Write the "object seeds" */
488 wr_u32b(current_world_ptr->seed_flavor);
489 wr_u32b(current_world_ptr->seed_town);
492 wr_u16b(creature_ptr->panic_save);
493 wr_u16b(current_world_ptr->total_winner);
494 wr_u16b(current_world_ptr->noscore);
497 wr_byte(creature_ptr->is_dead);
500 wr_byte(creature_ptr->feeling);
502 /* Turn when level began */
503 wr_s32b(creature_ptr->current_floor_ptr->generated_turn);
505 /* Turn of last "feeling" */
506 wr_s32b(creature_ptr->feeling_turn);
509 wr_s32b(current_world_ptr->game_turn);
511 wr_s32b(current_world_ptr->dungeon_turn);
513 wr_s32b(current_world_ptr->arena_start_turn);
516 wr_s16b(creature_ptr->today_mon);
517 wr_s16b(creature_ptr->riding);
519 /* Current floor_id */
520 wr_s16b(creature_ptr->floor_id);
522 /* Save temporary preserved pets (obsolated) */
525 wr_u32b(current_world_ptr->play_time);
526 wr_s32b(creature_ptr->visit);
527 wr_u32b(creature_ptr->count);
531 * @brief 保存フロアの書き込み / Actually write a saved floor data using effectively compressed format.
532 * @param sf_ptr 保存したいフロアの参照ポインタ
535 static void wr_saved_floor(player_type *player_ptr, saved_floor_type *sf_ptr)
538 /* Dungeon floor specific info follows */
539 floor_type *floor_ptr = player_ptr->current_floor_ptr;
541 /*** Not a saved floor ***/
543 wr_s16b((s16b)floor_ptr->dun_level);
545 /*** The saved floor ***/
547 wr_s16b(sf_ptr->floor_id);
548 wr_byte((byte)sf_ptr->savefile_id);
549 wr_s16b((s16b)sf_ptr->dun_level);
550 wr_s32b(sf_ptr->last_visit);
551 wr_u32b(sf_ptr->visit_mark);
552 wr_s16b(sf_ptr->upper_floor_id);
553 wr_s16b(sf_ptr->lower_floor_id);
556 wr_u16b((u16b)floor_ptr->base_level);
557 wr_u16b((s16b)player_ptr->current_floor_ptr->num_repro);
558 wr_u16b((u16b)player_ptr->y);
559 wr_u16b((u16b)player_ptr->x);
560 wr_u16b((u16b)floor_ptr->height);
561 wr_u16b((u16b)floor_ptr->width);
562 wr_byte(player_ptr->feeling);
564 /*********** Make template for grid_type **********/
567 * Usually number of templates are fewer than 255. Even if
568 * more than 254 are exist, the occurrence of each template
569 * with larger ID is very small when we sort templates by
570 * occurrence. So we will use two (or more) bytes for
571 * templete ID larger than 254.
573 * Ex: 256 will be "0xff" "0x01".
574 * 515 will be "0xff" "0xff" "0x03"
577 /* Fake max number */
578 u16b max_num_temp = 255;
580 /* Allocate the "template" array */
581 grid_template_type *templates;
582 C_MAKE(templates, max_num_temp, grid_template_type);
584 /* Extract template array */
586 for (int y = 0; y < floor_ptr->height; y++) {
587 for (int x = 0; x < floor_ptr->width; x++) {
588 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
591 for (i = 0; i < num_temp; i++) {
592 if (templates[i].info == g_ptr->info && templates[i].feat == g_ptr->feat && templates[i].mimic == g_ptr->mimic
593 && templates[i].special == g_ptr->special) {
594 /* Same terrain is exist */
595 templates[i].occurrence++;
600 /* Are there same one? */
604 /* If the max_num_temp is too small, increase it. */
605 if (num_temp >= max_num_temp) {
606 grid_template_type *old_template = templates;
608 /* Re-allocate the "template" array */
609 C_MAKE(templates, max_num_temp + 255, grid_template_type);
610 (void)C_COPY(templates, old_template, max_num_temp, grid_template_type);
611 C_KILL(old_template, max_num_temp, grid_template_type);
615 /* Add new template */
616 templates[num_temp].info = g_ptr->info;
617 templates[num_temp].feat = g_ptr->feat;
618 templates[num_temp].mimic = g_ptr->mimic;
619 templates[num_temp].special = g_ptr->special;
620 templates[num_temp].occurrence = 1;
622 /* Increase number of template */
627 /* Sort by occurrence */
629 ang_sort(player_ptr, templates, &dummy_why, num_temp, ang_sort_comp_cave_temp, ang_sort_swap_cave_temp);
631 /*** Dump templates ***/
633 /* Total templates */
636 /* Dump the templates */
637 for (int i = 0; i < num_temp; i++) {
638 grid_template_type *ct_ptr = &templates[i];
639 wr_u16b((u16b)ct_ptr->info);
640 wr_s16b(ct_ptr->feat);
641 wr_s16b(ct_ptr->mimic);
642 wr_s16b(ct_ptr->special);
645 /*** "Run-Length-Encoding" of floor ***/
646 /* Note that this will induce two wasted bytes */
650 for (int y = 0; y < floor_ptr->height; y++) {
651 for (int x = 0; x < floor_ptr->width; x++) {
652 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
654 for (i = 0; i < num_temp; i++) {
655 if (templates[i].info == g_ptr->info && templates[i].feat == g_ptr->feat && templates[i].mimic == g_ptr->mimic
656 && templates[i].special == g_ptr->special)
661 u16b tmp16u = (u16b)i;
663 /* If the run is broken, or too full, flush it */
664 if ((tmp16u == prev_u16b) && (count != MAX_UCHAR)) {
669 wr_byte((byte)count);
671 while (prev_u16b >= MAX_UCHAR) {
672 /* Mark as actual data is larger than 254 */
674 prev_u16b -= MAX_UCHAR;
677 wr_byte((byte)prev_u16b);
683 /* Flush the data (if any) */
685 wr_byte((byte)count);
687 while (prev_u16b >= MAX_UCHAR) {
688 /* Mark as actual data is larger than 254 */
690 prev_u16b -= MAX_UCHAR;
693 wr_byte((byte)prev_u16b);
696 /* Free the "template" array */
697 C_KILL(templates, max_num_temp, grid_template_type);
699 /*** Dump objects ***/
702 wr_u16b(floor_ptr->o_max);
704 /* Dump the objects */
705 for (int i = 1; i < floor_ptr->o_max; i++) {
706 object_type *o_ptr = &floor_ptr->o_list[i];
710 /*** Dump the monsters ***/
713 wr_u16b(floor_ptr->m_max);
715 /* Dump the monsters */
716 for (int i = 1; i < floor_ptr->m_max; i++) {
717 monster_type *m_ptr = &floor_ptr->m_list[i];
723 * @brief 現在フロアの書き込み /
724 * Write the current dungeon (new method)
725 * @player_ptr プレーヤーへの参照ポインタ
726 * @return 保存に成功したらTRUE
728 static bool wr_dungeon(player_type *player_ptr)
730 forget_lite(player_ptr->current_floor_ptr);
731 forget_view(player_ptr->current_floor_ptr);
732 clear_mon_lite(player_ptr->current_floor_ptr);
734 /* Update lite/view */
735 player_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
736 player_ptr->update |= (PU_MONSTERS | PU_DISTANCE | PU_FLOW);
740 /* Number of floor_id used from birth */
741 wr_s16b(max_floor_id);
743 /* Current dungeon type */
744 wr_byte((byte)player_ptr->dungeon_idx);
746 /*** No saved floor (On the surface etc.) ***/
747 if (!player_ptr->floor_id) {
748 /* No array elements */
751 /* Write the current floor data */
752 wr_saved_floor(player_ptr, NULL);
758 /*** In the dungeon ***/
760 /* Number of array elements */
761 wr_byte(MAX_SAVED_FLOORS);
763 /* Write the saved_floors array */
764 for (int i = 0; i < MAX_SAVED_FLOORS; i++) {
765 saved_floor_type *sf_ptr = &saved_floors[i];
767 wr_s16b(sf_ptr->floor_id);
768 wr_byte((byte)sf_ptr->savefile_id);
769 wr_s16b((s16b)sf_ptr->dun_level);
770 wr_s32b(sf_ptr->last_visit);
771 wr_u32b(sf_ptr->visit_mark);
772 wr_s16b(sf_ptr->upper_floor_id);
773 wr_s16b(sf_ptr->lower_floor_id);
776 /* Extract pointer to current floor */
777 saved_floor_type *cur_sf_ptr;
778 cur_sf_ptr = get_sf_ptr(player_ptr->floor_id);
780 /* Save current floor to temporary file */
781 if (!save_floor(player_ptr, cur_sf_ptr, (SLF_SECOND)))
784 /* Move data in temporary files to the savefile */
785 for (int i = 0; i < MAX_SAVED_FLOORS; i++) {
786 saved_floor_type *sf_ptr = &saved_floors[i];
787 if (!sf_ptr->floor_id)
789 if (!load_floor(player_ptr, sf_ptr, (SLF_SECOND | SLF_NO_KILL))) {
795 wr_saved_floor(player_ptr, sf_ptr);
798 if (!load_floor(player_ptr, cur_sf_ptr, (SLF_SECOND)))
804 * @brief セーブデータの書き込み /
805 * Actually write a save-file
806 * @param player_ptr プレーヤーへの参照ポインタ
809 static bool wr_savefile_new(player_type *player_ptr)
811 /* Compact the objects */
812 compact_objects(player_ptr, 0);
814 /* Compact the monsters */
815 compact_monsters(player_ptr, 0);
817 /* Guess at the current time */
818 u32b now = (u32b)time((time_t *)0);
820 /* Note the operating system */
821 current_world_ptr->sf_system = 0L;
823 /* Note when the file was saved */
824 current_world_ptr->sf_when = now;
826 /* Note the number of saves */
827 current_world_ptr->sf_saves++;
829 /*** Actually write the file ***/
830 /* Dump the file header */
832 wr_byte(FAKE_VER_MAJOR);
834 wr_byte(FAKE_VER_MINOR);
836 wr_byte(FAKE_VER_PATCH);
839 /* Initial value of xor_byte */
840 byte tmp8u = (byte)Rand_external(256);
843 /* Reset the checksum */
847 /* Write the savefile version for Hengband 1.1.1 and later */
848 wr_byte(H_VER_EXTRA);
849 wr_byte(H_VER_PATCH);
850 wr_byte(H_VER_MINOR);
851 wr_byte(H_VER_MAJOR);
853 /* Operating system */
854 wr_u32b(current_world_ptr->sf_system);
856 /* Time file last saved */
857 wr_u32b(current_world_ptr->sf_when);
859 /* Number of past lives */
860 wr_u16b(current_world_ptr->sf_lives);
862 /* Number of times saved */
863 wr_u16b(current_world_ptr->sf_saves);
875 /* SJIS kanji code */
883 /* Write the RNG state */
886 /* Write the boolean "options" */
889 /* Dump the number of "messages" */
890 u32b tmp32u = message_num();
891 if (compress_savefile && (tmp32u > 40))
895 /* Dump the messages (oldest first!) */
896 for (int i = tmp32u - 1; i >= 0; i--) {
897 wr_string(message_str((s16b)i));
900 /* Dump the monster lore */
901 u16b tmp16u = max_r_idx;
903 for (MONRACE_IDX r_idx = 0; r_idx < tmp16u; r_idx++) {
907 /* Dump the object memory */
910 for (KIND_OBJECT_IDX k_idx = 0; k_idx < tmp16u; k_idx++) {
918 /* Dump the quests */
922 /* Dump the quests */
923 tmp8u = MAX_RANDOM_QUEST - MIN_RANDOM_QUEST;
926 for (int i = 0; i < max_q_idx; i++) {
927 quest_type *const q_ptr = &quest[i];
929 /* Save status for every quest */
930 wr_s16b(q_ptr->status);
932 /* And the dungeon level too */
933 /* (prevents problems with multi-level quests) */
934 wr_s16b((s16b)q_ptr->level);
936 wr_byte((byte)q_ptr->complev);
937 wr_u32b(q_ptr->comptime);
939 bool is_quest_running = q_ptr->status == QUEST_STATUS_TAKEN;
940 is_quest_running |= q_ptr->status == QUEST_STATUS_COMPLETED;
941 is_quest_running |= !is_fixed_quest_idx(i);
942 if (!is_quest_running)
945 wr_s16b((s16b)q_ptr->cur_num);
946 wr_s16b((s16b)q_ptr->max_num);
947 wr_s16b(q_ptr->type);
948 wr_s16b(q_ptr->r_idx);
949 wr_s16b(q_ptr->k_idx);
950 wr_byte((byte)q_ptr->flags);
951 wr_byte((byte)q_ptr->dungeon);
954 /* Dump the position in the wilderness */
955 wr_s32b(player_ptr->wilderness_x);
956 wr_s32b(player_ptr->wilderness_y);
958 wr_byte(player_ptr->wild_mode);
959 wr_byte(player_ptr->ambush_flag);
961 wr_s32b(current_world_ptr->max_wild_x);
962 wr_s32b(current_world_ptr->max_wild_y);
964 /* Dump the wilderness seeds */
965 for (int i = 0; i < current_world_ptr->max_wild_x; i++) {
966 for (int j = 0; j < current_world_ptr->max_wild_y; j++) {
967 wr_u32b(wilderness[j][i].seed);
971 /* Hack -- Dump the artifacts */
974 for (int i = 0; i < tmp16u; i++) {
975 artifact_type *a_ptr = &a_info[i];
976 wr_byte(a_ptr->cur_num);
977 wr_s16b(a_ptr->floor_id);
980 /* Write the "extra" information */
981 wr_extra(player_ptr);
983 /* Dump the "player hp" entries */
984 tmp16u = PY_MAX_LEVEL;
986 for (int i = 0; i < tmp16u; i++) {
987 wr_s16b((s16b)player_ptr->player_hp[i]);
990 /* Write spell data */
991 wr_u32b(player_ptr->spell_learned1);
992 wr_u32b(player_ptr->spell_learned2);
993 wr_u32b(player_ptr->spell_worked1);
994 wr_u32b(player_ptr->spell_worked2);
995 wr_u32b(player_ptr->spell_forgotten1);
996 wr_u32b(player_ptr->spell_forgotten2);
998 wr_s16b(player_ptr->learned_spells);
999 wr_s16b(player_ptr->add_spells);
1001 /* Dump the ordered spells */
1002 for (int i = 0; i < 64; i++) {
1003 wr_byte((byte)player_ptr->spell_order[i]);
1006 for (int i = 0; i < INVEN_TOTAL; i++) {
1007 object_type *o_ptr = &player_ptr->inventory_list[i];
1018 /* Add a sentinel */
1021 /* Note the towns */
1025 /* Note the stores */
1026 tmp16u = MAX_STORES;
1029 /* Dump the stores of all towns */
1030 for (int i = 1; i < max_towns; i++) {
1031 for (int j = 0; j < MAX_STORES; j++) {
1032 wr_store(&town_info[i].store[j]);
1036 /* Write the pet command settings */
1037 wr_s16b(player_ptr->pet_follow_distance);
1038 wr_s16b(player_ptr->pet_extra_flags);
1040 /* Write screen dump for sending score */
1041 if (screen_dump && (player_ptr->wait_report_score || !player_ptr->is_dead)) {
1042 wr_string(screen_dump);
1047 /* Player is not dead, write the dungeon */
1048 if (!player_ptr->is_dead) {
1049 /* Dump the dungeon */
1050 if (!wr_dungeon(player_ptr))
1053 /* Dump the ghost */
1060 /* Write the "value check-sum" */
1063 /* Write the "encoded checksum" */
1066 if (ferror(saving_savefile) || (fflush(saving_savefile) == EOF))
1072 * @brief セーブデータ書き込みのサブルーチン /
1073 * Medium level player saver
1074 * @param player_ptr プレーヤーへの参照ポインタ
1077 * Angband 2.8.0 will use "fd" instead of "fff" if possible
1079 static bool save_player_aux(player_type *player_ptr, char *name)
1081 /* Grab permissions */
1082 safe_setuid_grab(player_ptr);
1084 /* Create the savefile */
1085 int file_permission = 0644;
1086 int fd = fd_make(name, file_permission);
1088 /* Drop permissions */
1091 bool is_save_successful = FALSE;
1092 saving_savefile = NULL;
1094 /* Close the "fd" */
1097 /* Grab permissions */
1098 safe_setuid_grab(player_ptr);
1100 /* Open the savefile */
1101 saving_savefile = angband_fopen(name, "wb");
1103 /* Drop permissions */
1106 /* Successful open */
1107 if (saving_savefile) {
1108 /* Write the savefile */
1109 if (wr_savefile_new(player_ptr))
1110 is_save_successful = TRUE;
1112 /* Attempt to close it */
1113 if (angband_fclose(saving_savefile))
1114 is_save_successful = FALSE;
1117 /* Grab permissions */
1118 safe_setuid_grab(player_ptr);
1120 /* Remove "broken" files */
1121 if (!is_save_successful)
1122 (void)fd_kill(name);
1124 /* Drop permissions */
1128 if (!is_save_successful)
1131 counts_write(player_ptr, 0, current_world_ptr->play_time);
1132 current_world_ptr->character_saved = TRUE;
1137 * @brief セーブデータ書き込みのメインルーチン /
1138 * Attempt to save the player in a savefile
1139 * @param player_ptr プレーヤーへの参照ポインタ
1142 bool save_player(player_type *player_ptr)
1145 strcpy(safe, savefile);
1146 strcat(safe, ".new");
1148 /* Grab permissions */
1149 safe_setuid_grab(player_ptr);
1153 /* Drop permissions */
1157 /* Attempt to save the player */
1158 bool result = FALSE;
1159 if (save_player_aux(player_ptr, safe)) {
1163 strcpy(temp, savefile);
1164 strcat(temp, ".old");
1166 /* Grab permissions */
1167 safe_setuid_grab(player_ptr);
1172 /* Preserve old savefile */
1173 fd_move(savefile, temp);
1175 /* Activate new savefile */
1176 fd_move(safe, savefile);
1178 /* Remove preserved savefile */
1181 /* Drop permissions */
1184 /* Hack -- Pretend the character was loaded */
1185 current_world_ptr->character_loaded = TRUE;
1190 /* Return the result */
1195 * @brief セーブデータ読み込みのメインルーチン /
1196 * Attempt to Load a "savefile"
1197 * @param creature_ptr プレーヤーへの参照ポインタ
1201 * Version 2.7.0 introduced a slightly different "savefile" format from
1202 * older versions, requiring a completely different parsing method.
1204 * Note that savefiles from 2.7.0 - 2.7.2 are completely obsolete.
1206 * Pre-2.8.0 savefiles lose some data, see "load2.c" for info.
1208 * Pre-2.7.0 savefiles lose a lot of things, see "load1.c" for info.
1210 * On multi-user systems, you may only "read" a savefile if you will be
1211 * allowed to "write" it later, this prevents painful situations in which
1212 * the player loads a savefile belonging to someone else, and then is not
1213 * allowed to save his game when he quits.
1215 * We return "TRUE" if the savefile was usable, and we set the global
1216 * flag "current_world_ptr->character_loaded" if a real, living, character was loaded.
1218 * Note that we always try to load the "current" savefile, even if
1219 * there is no such file, so we must check for "empty" savefile names.
1222 bool load_player(player_type *player_ptr)
1224 concptr what = "generic";
1226 current_world_ptr->game_turn = 0;
1227 player_ptr->is_dead = FALSE;
1229 /* Allow empty savefile name */
1233 #if !defined(WINDOWS)
1237 /* Verify the existance of the savefile */
1238 if (access(savefile, 0) < 0) {
1239 /* Give a message */
1240 msg_print(_("セーブファイルがありません。", "Savefile does not exist."));
1254 /* Open the savefile */
1255 fd = fd_open(savefile, O_RDONLY);
1261 /* Message (below) */
1263 what = _("セーブファイルを開けません。", "Cannot open savefile");
1268 /* Read the first four bytes */
1269 if (fd_read(fd, (char *)(vvv), 4))
1274 what = _("セーブファイルを読めません。", "Cannot read savefile");
1280 /* Extract version */
1281 current_world_ptr->z_major = vvv[0];
1282 current_world_ptr->z_minor = vvv[1];
1283 current_world_ptr->z_patch = vvv[2];
1284 current_world_ptr->sf_extra = vvv[3];
1288 /* Attempt to load */
1289 err = rd_savefile(player_ptr);
1291 /* Message (below) */
1293 what = _("セーブファイルを解析出来ません。", "Cannot parse savefile");
1298 if (!current_world_ptr->game_turn)
1301 /* Message (below) */
1303 what = _("セーブファイルが壊れています", "Broken savefile");
1307 /* Give a conversion warning */
1308 if ((FAKE_VER_MAJOR != current_world_ptr->z_major) || (FAKE_VER_MINOR != current_world_ptr->z_minor)
1309 || (FAKE_VER_PATCH != current_world_ptr->z_patch)) {
1310 if (current_world_ptr->z_major == 2 && current_world_ptr->z_minor == 0 && current_world_ptr->z_patch == 6) {
1311 msg_print(_("バージョン 2.0.* 用のセーブファイルを変換しました。", "Converted a 2.0.* savefile."));
1313 msg_format(_("バージョン %d.%d.%d 用のセーブ・ファイルを変換しました。", "Converted a %d.%d.%d savefile."),
1314 (current_world_ptr->z_major > 9) ? current_world_ptr->z_major - 10 : current_world_ptr->z_major, current_world_ptr->z_minor,
1315 current_world_ptr->z_patch);
1320 /* Player is dead */
1321 if (player_ptr->is_dead) {
1324 /* A character was loaded */
1325 current_world_ptr->character_loaded = TRUE;
1329 /* Player is no longer "dead" */
1330 player_ptr->is_dead = FALSE;
1333 current_world_ptr->sf_lives++;
1338 /* A character was loaded */
1339 current_world_ptr->character_loaded = TRUE;
1342 u32b tmp = counts_read(player_ptr, 2);
1343 if (tmp > player_ptr->count)
1344 player_ptr->count = tmp;
1345 if (counts_read(player_ptr, 0) > current_world_ptr->play_time || counts_read(player_ptr, 1) == current_world_ptr->play_time)
1346 counts_write(player_ptr, 2, ++player_ptr->count);
1347 counts_write(player_ptr, 1, current_world_ptr->play_time);
1354 msg_format(_("エラー(%s)がバージョン%d.%d.%d 用セーブファイル読み込み中に発生。", "Error (%s) reading %d.%d.%d savefile."), what,
1355 (current_world_ptr->z_major > 9) ? current_world_ptr->z_major - 10 : current_world_ptr->z_major, current_world_ptr->z_minor,
1356 current_world_ptr->z_patch);
1362 * @brief ゲームプレイ中のフロア一時保存出力処理サブルーチン / Actually write a temporary saved floor file
1363 * @param player_ptr プレーヤーへの参照ポインタ
1364 * @param sf_ptr 保存フロア参照ポインタ
1367 static bool save_floor_aux(player_type *player_ptr, saved_floor_type *sf_ptr)
1369 /* Compact the objects */
1370 compact_objects(player_ptr, 0);
1371 /* Compact the monsters */
1372 compact_monsters(player_ptr, 0);
1374 /*** Actually write the file ***/
1375 /* Initial value of xor_byte */
1376 byte tmp8u = (byte)randint0(256);
1380 /* Reset the checksum */
1384 /* Write the sign of this process */
1385 wr_u32b(saved_floor_file_sign);
1387 /* Dump the dungeon floor */
1388 wr_saved_floor(player_ptr, sf_ptr);
1390 /* Write the "value check-sum" */
1393 /* Write the "encoded checksum" */
1396 if (ferror(saving_savefile) || (fflush(saving_savefile) == EOF))
1402 * @brief ゲームプレイ中のフロア一時保存出力処理メインルーチン / Attempt to save the temporarily saved-floor data
1403 * @param player_ptr プレーヤーへの参照ポインタ
1404 * @param sf_ptr 保存フロア参照ポインタ
1405 * @param mode 保存オプション
1408 bool save_floor(player_type *player_ptr, saved_floor_type *sf_ptr, BIT_FLAGS mode)
1410 FILE *old_fff = NULL;
1411 byte old_xor_byte = 0;
1412 u32b old_v_stamp = 0;
1413 u32b old_x_stamp = 0;
1415 char floor_savefile[1024];
1416 if (!(mode & SLF_SECOND)) {
1419 /* We have one file already opened */
1421 /* Backup original values */
1422 old_fff = saving_savefile;
1423 old_xor_byte = save_xor_byte;
1424 old_v_stamp = v_stamp;
1425 old_x_stamp = x_stamp;
1429 sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
1431 /* Grab permissions */
1432 safe_setuid_grab(player_ptr);
1435 fd_kill(floor_savefile);
1437 /* Drop permissions */
1440 /* Attempt to save the player */
1443 saving_savefile = NULL;
1445 /* Grab permissions */
1446 safe_setuid_grab(player_ptr);
1448 /* Create the savefile */
1449 int fd = fd_make(floor_savefile, 0644);
1451 /* Drop permissions */
1454 bool is_save_successful = FALSE;
1456 /* Close the "fd" */
1459 /* Grab permissions */
1460 safe_setuid_grab(player_ptr);
1462 /* Open the savefile */
1463 saving_savefile = angband_fopen(floor_savefile, "wb");
1465 /* Drop permissions */
1468 /* Successful open */
1469 if (saving_savefile) {
1470 /* Write the savefile */
1471 if (save_floor_aux(player_ptr, sf_ptr))
1472 is_save_successful = TRUE;
1474 /* Attempt to close it */
1475 if (angband_fclose(saving_savefile))
1476 is_save_successful = FALSE;
1479 /* Remove "broken" files */
1480 if (!is_save_successful) {
1481 /* Grab permissions */
1482 safe_setuid_grab(player_ptr);
1484 (void)fd_kill(floor_savefile);
1486 /* Drop permissions */
1491 if (!(mode & SLF_SECOND)) {
1494 /* We have one file already opened */
1496 /* Restore original values */
1497 saving_savefile = old_fff;
1498 save_xor_byte = old_xor_byte;
1499 v_stamp = old_v_stamp;
1500 x_stamp = old_x_stamp;
1503 return is_save_successful;