/* * Read the dungeon * * The monsters/objects must be loaded in the same order * that they were stored, since the actual indexes matter. * * Note that the size of the dungeon is now hard-coded to * DUNGEON_HGT by DUNGEON_WID, and any dungeon with another * size will be silently discarded by this routine. * * Note that dungeon objects, including objects held by monsters, are * placed directly into the dungeon, using "object_copy()", which will * copy "iy", "ix", and "held_m_idx", leaving "next_o_idx" blank for * objects held by monsters, since it is not saved in the savefile. * * After loading the monsters, the objects being held by monsters are * linked directly into those monsters. */ static errr rd_dungeon(void) { int i, y, x; s16b depth; s16b py, px; byte count; byte tmp8u; u16b tmp16u; u16b limit; /*** Basic info ***/ /* Header info */ rd_s16b(&depth); rd_u16b(&p_ptr->dungeon_type); /* Get dungeon capabilities */ set_dungeon_type(p_ptr->dungeon_type); rd_s16b(&py); rd_s16b(&px); rd_byte(&p_ptr->cur_map_hgt); rd_byte(&p_ptr->cur_map_wid); rd_u16b(&altered_inventory_counter); /* Paranoia */ allow_altered_inventory = FALSE; rd_u16b(&tmp16u); /* Ignore illegal dungeons */ if ((depth < 0) || (depth >= MAX_DEPTH)) { note(format("Ignoring illegal dungeon depth (%d)", depth)); return (0); } /* Ignore illegal dungeons */ if ((p_ptr->cur_map_hgt > MAX_DUNGEON_HGT) || (p_ptr->cur_map_wid > MAX_DUNGEON_WID)) { /* XXX XXX XXX */ note(format("Ignoring illegal dungeon size (%d,%d).", p_ptr->cur_map_hgt, p_ptr->cur_map_wid)); return (0); } /* Ignore illegal dungeons */ if ((px < 0) || (px >= p_ptr->cur_map_wid) || (py < 0) || (py >= p_ptr->cur_map_hgt)) { note(format("Ignoring illegal player location (%d,%d).", py, px)); return (1); } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < p_ptr->cur_map_hgt; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Extract "info" */ cave_info[y][x] = tmp8u; /* Advance/Wrap */ if (++x >= p_ptr->cur_map_wid) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= p_ptr->cur_map_hgt) break; } } } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < p_ptr->cur_map_hgt; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { feature_type *f_ptr; /* Extract "feat" */ cave_feat[y][x] = tmp8u; update_los_proj_move(y, x); /* Get fast access to feature */ f_ptr = &f_info[tmp8u]; /* Handle glowing grids */ if (_feat_ff2_match(f_ptr, FF2_GLOW)) { int d; /* Turn on super glow */ cave_info[y][x] |= (CAVE_HALO); /* Spread super glow through adjacent grids */ for (d = 0; d < 8; d++) { /* Get coordinates */ int yy = y + ddy_ddd[d]; int xx = x + ddx_ddd[d]; /* Ignore annoying locations */ if (!in_bounds_fully(yy, xx)) { continue; } /* Turn on super glow */ cave_info[yy][xx] |= (CAVE_HALO); } } /* Register dynamic features */ if (_feat_ff3_match(f_ptr, FF3_DYNAMIC)) { (void)add_dynamic_terrain(y, x); } /* Update the flags of the current level */ if (_feat_ff3_match(f_ptr, TERRAIN_MASK)) { level_flag |= get_level_flag((u16b)(f_ptr - f_info)); } /* Advance/Wrap */ if (++x >= p_ptr->cur_map_wid) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= p_ptr->cur_map_hgt) break; } } } /*** Player ***/ /* Load depth */ p_ptr->depth = depth; /* Place player in dungeon */ if (!player_place(py, px)) { note(format("Cannot place player (%d,%d)!", py, px)); return (-1); } /*** Objects ***/ /* Read the item count */ rd_u16b(&limit); /* Verify maximum */ if (limit > z_info->o_max) { note(format("Too many (%d) object entries!", limit)); return (-1); } /* Read the dungeon items */ for (i = 1; i < limit; i++) { object_type *i_ptr; object_type object_type_body; s16b o_idx; object_type *o_ptr; /* Get the object */ i_ptr = &object_type_body; /* Wipe the object */ object_wipe(i_ptr); /* Read the item */ if (rd_item(i_ptr)) { note("Error reading item"); return (-1); } /* Make an object */ o_idx = o_pop(); /* Paranoia */ if (o_idx != i) { note(format("Cannot place object %d!", i)); return (-1); } /* Get the object */ o_ptr = &o_list[o_idx]; /* Structure Copy */ object_copy(o_ptr, i_ptr); /* Dungeon floor */ if (!i_ptr->held_m_idx) { int x = i_ptr->ix; int y = i_ptr->iy; /* ToDo: Verify coordinates */ /* Link the object to the pile */ o_ptr->next_o_idx = cave_o_idx[y][x]; /* Link the floor to the object */ cave_o_idx[y][x] = o_idx; /* Rearrange stack if needed */ rearrange_stack(y, x); } } /*** Monsters ***/ /* Read the monster count */ rd_u16b(&limit); /* Hack -- verify */ if (limit > z_info->m_max) { note(format("Too many (%d) monster entries!", limit)); return (-1); } /* Read the monsters */ for (i = 1; i < limit; i++) { monster_type *n_ptr; monster_type monster_type_body; monster_race *r_ptr; int r_idx; /* Get local monster */ n_ptr = &monster_type_body; /* Clear the monster */ (void)WIPE(n_ptr, monster_type); /* Read the monster */ rd_monster(n_ptr); /* Access the "r_idx" of the chosen monster */ r_idx = n_ptr->r_idx; /* Access the actual race */ r_ptr = &r_info[r_idx]; /* If a player ghost, some special features need to be added. */ if (r_ptr->flags2 & (RF2_PLAYER_GHOST)) { (void)prepare_ghost(n_ptr->r_idx); } /* Place monster in dungeon */ if (monster_place(n_ptr->fy, n_ptr->fx, n_ptr) != i) { note(format("Cannot place monster %d", i)); return (-1); } } /*** Holding ***/ /* Reacquire objects */ for (i = 1; i < o_max; ++i) { object_type *o_ptr; monster_type *m_ptr; /* Get the object */ o_ptr = &o_list[i]; /* Ignore dungeon objects */ if (!o_ptr->held_m_idx) continue; /* Verify monster index */ if (o_ptr->held_m_idx > z_info->m_max) { note("Invalid monster index"); return (-1); } /* Get the monster */ m_ptr = &mon_list[o_ptr->held_m_idx]; /* Link the object to the pile */ o_ptr->next_o_idx = m_ptr->hold_o_idx; /* Link the monster to the object */ m_ptr->hold_o_idx = i; } /*** Effects ***/ /* Read the effect count */ rd_u16b(&limit); /* Verify maximum */ if (limit > z_info->x_max) { note(format("Too many (%d) effect entries!", limit)); return (-1); } /* Read the dungeon items */ for (i = 1; i < limit; i++) { /* Read the item */ if (rd_effect()) { note("Error reading effect"); return (-1); } } /*** Success ***/ /* The dungeon is ready */ character_dungeon = TRUE; /* Success */ return (0); }
/* * Read the "extra" information */ static errr rd_extra(void) { int i; byte tmp8u; u16b tmp16u; u16b file_e_max; byte num; rd_string(op_ptr->full_name, sizeof(op_ptr->full_name)); rd_string(p_ptr->died_from, 80); rd_string(p_ptr->history, 250); /* Player race */ rd_byte(&p_ptr->prace); /* Verify player race */ if (p_ptr->prace >= z_info->p_max) { note(format("Invalid player race (%d).", p_ptr->prace)); return (-1); } /* Player class */ rd_byte(&p_ptr->pclass); /* Verify player class */ if (p_ptr->pclass >= z_info->c_max) { note(format("Invalid player class (%d).", p_ptr->pclass)); return (-1); } /* Player gender */ rd_byte(&p_ptr->psex); strip_bytes(1); /* Special Race/Class info */ rd_byte(&p_ptr->hitdie); rd_byte(&p_ptr->expfact); /* Age/Height/Weight */ rd_s16b(&p_ptr->age); rd_s16b(&p_ptr->ht); rd_s16b(&p_ptr->wt); /* Read the stat info */ for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_max[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_cur[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_birth[i]); for (i = 0; i < A_MAX; ++i) rd_s16b(&p_ptr->stat_quest_add[i]); rd_s16b(&p_ptr->ht_birth); rd_s16b(&p_ptr->wt_birth); rd_s16b(&p_ptr->sc_birth); rd_s32b(&p_ptr->au_birth); strip_bytes(24); /* oops */ rd_u16b(&p_ptr->q_fame); rd_u16b(&p_ptr->deferred_rewards); rd_s32b(&p_ptr->au); rd_s32b(&p_ptr->max_exp); rd_s32b(&p_ptr->exp); rd_u16b(&p_ptr->exp_frac); rd_s16b(&p_ptr->lev); /* Verify player level */ if ((p_ptr->lev < 1) || (p_ptr->lev > z_info->max_level)) { note(format("Invalid player level (%d).", p_ptr->lev)); return (-1); } rd_s16b(&p_ptr->mhp); rd_s16b(&p_ptr->chp); rd_u16b(&p_ptr->chp_frac); rd_s16b(&p_ptr->msp); rd_s16b(&p_ptr->csp); rd_u16b(&p_ptr->csp_frac); rd_s16b(&p_ptr->max_lev); rd_s16b(&p_ptr->max_depth); rd_s16b(&p_ptr->recall_depth); /* Hack -- Repair maximum player level */ if (p_ptr->max_lev < p_ptr->lev) p_ptr->max_lev = p_ptr->lev; /* Hack -- Repair maximum dungeon level */ if (p_ptr->max_depth < 0) p_ptr->max_depth = 1; /* Hack -- Repair recall dungeon level */ if (p_ptr->recall_depth < 0) p_ptr->recall_depth = 1; rd_s16b(&p_ptr->quest_depth); /* Hack -- Repair max quest level */ if ((p_ptr->max_depth > 1) && (p_ptr->max_depth > p_ptr->quest_depth)) { p_ptr->quest_depth = p_ptr->max_depth; } /* More info */ strip_bytes(6); rd_s16b(&p_ptr->sc); strip_bytes(2); /* Read the flags */ strip_bytes(2); /* Old "rest" */ rd_s16b(&p_ptr->food); strip_bytes(4); /* Old "food_digested" / "protection" */ rd_s16b(&p_ptr->p_energy); rd_s16b(&p_ptr->word_recall); rd_s16b(&p_ptr->state.see_infra); rd_byte(&p_ptr->confusing); rd_byte(&tmp8u); rd_byte(&p_ptr->searching); rd_byte(&tmp8u); /* oops */ rd_byte(&tmp8u); /* oops */ rd_byte(&tmp8u); /* oops */ /* Find the number of timed effects */ rd_byte(&num); if (num == TMD_MAX) { /* Read all the effects */ for (i = 0; i < num; i++) rd_s16b(&p_ptr->timed[i]); } else { s16b dummy2; /* Probably in trouble anyway */ for (i = 0; i < TMD_MAX; i++) rd_s16b(&dummy2); /* Discard unused entries */ note("Discarding unsupported timed effects"); } rd_s16b(&p_ptr->base_wakeup_chance); rd_s16b(&total_wakeup_chance); /* Read item-quality squelch sub-menu */ for (i = 0; i < SQUELCH_BYTES; i++) rd_byte(&squelch_level[i]); /* Load the name of the current greater vault */ rd_string(g_vault_name, sizeof(g_vault_name)); /* Read the number of saved ego-item types */ rd_u16b(&file_e_max); /* Read ego-item squelch settings */ for (i = 0; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; tmp8u = 0; if (i < file_e_max) rd_byte(&tmp8u); e_ptr->squelch |= (tmp8u & 0x01); e_ptr->everseen |= (tmp8u & 0x02); /* Hack - Repair the savefile */ if (!e_ptr->everseen) e_ptr->squelch = FALSE; } /* Read possible extra elements */ while (i < file_e_max) { rd_byte(&tmp8u); i++; } /*Read the current number of auto-inscriptions*/ rd_u16b(&inscriptionsCount); /*Read the autoinscriptions array*/ for(i = 0; i < inscriptionsCount; i++) { char tmp[80]; rd_s16b(&inscriptions[i].kindIdx); rd_string(tmp, 80); inscriptions[i].inscriptionIdx = quark_add(tmp); } /* * The number of the bone file (if any) that player ghosts should use to * derive the ghost name, sex, class, race, and level. */ rd_s16b(&player_ghost_num); /* Find out how many thefts have recently occurred. */ strip_bytes(1); /* Read number of monster traps on level. */ rd_byte(&num_trap_on_level); /* Future use */ strip_bytes(13); /* Read the summon spells that have already failed on the level */ rd_u32b(&dungeon_summon_mask_f7); /* Read the randart seed */ rd_u32b(&seed_randart); /* Skip the flags */ strip_bytes(12); /* Hack -- the three "special seeds" */ rd_u32b(&seed_flavor); rd_u32b(&seed_town); rd_u32b(&seed_ghost); /* Special stuff */ rd_u16b(&p_ptr->panic_save); rd_u16b(&p_ptr->total_winner); rd_u16b(&p_ptr->noscore); /* Read "death" */ rd_byte(&tmp8u); p_ptr->is_dead = tmp8u; /* Read "feeling" */ rd_byte(&tmp8u); feeling = tmp8u; /*read the level feeling*/ rd_byte(&tmp8u); do_feeling = tmp8u; /* Current turn */ rd_s32b(&turn); /*Current Player Turn*/ rd_s32b(&p_ptr->p_turn); /* Turn count for quest indicator */ rd_u16b(&quest_indicator_timer); /* Check if the quest indicator must flash the victory sign */ if (quest_indicator_timer & (QUEST_INDICATOR_COMPLETE_BIT)) { /* We won the quest */ quest_indicator_complete = TRUE; /* Clear the mark from the timer */ quest_indicator_timer &= ~(QUEST_INDICATOR_COMPLETE_BIT); } /* Panel change offsets */ rd_u16b(&panel_change_offset_y); rd_u16b(&panel_change_offset_x); /* Check bounds */ if (panel_change_offset_y < MIN_PANEL_CHANGE_OFFSET_Y) { panel_change_offset_y = MIN_PANEL_CHANGE_OFFSET_Y; } if (panel_change_offset_x < MIN_PANEL_CHANGE_OFFSET_X) { panel_change_offset_x = MIN_PANEL_CHANGE_OFFSET_X; } /* Read the player_hp array */ rd_u16b(&tmp16u); /* Incompatible save files */ if (tmp16u > z_info->max_level) { note(format("Too many (%u) hitpoint entries!", tmp16u)); return (-1); } /* Read the player_hp array */ for (i = 0; i < tmp16u; i++) { rd_s16b(&p_ptr->player_hp[i]); } /* Read the player spells */ if (rd_player_spells()) return (-1); return (0); }
/* * Read the random artifacts */ static errr rd_randarts(void) { int i; byte tmp8u; s16b tmp16s; u16b tmp16u; u16b artifact_count, begin; s32b tmp32s; u32b tmp32u; /* Read the number of artifacts */ rd_u16b(&begin); rd_u16b(&artifact_count); rd_u16b(&art_norm_count); /* Alive or cheating death */ if (!p_ptr->is_dead || arg_wizard) { /* Incompatible save files */ if ((artifact_count > z_info->art_max) || (art_norm_count > z_info->art_norm_max)) { note(format("Too many (%u) artifacts!", artifact_count)); return (-1); } /*Mark any new added artifacts*/ if (art_norm_count < z_info->art_norm_max) { new_artifacts = z_info->art_norm_max - art_norm_count; } else new_artifacts = 0; /* Mark the old artifacts as "empty" */ for (i = begin; i < z_info->art_max; i++) { artifact_type *a_ptr = &a_info[i]; /*hack - if a new "normal artifact has been added in mid-game, don't erase it*/ if ((i >= art_norm_count) && (i < z_info->art_norm_max)) continue; a_ptr->tval = 0; a_ptr->sval = 0; a_ptr->name[0] = '\0'; } /* Read the artifacts */ for (i = begin; i < artifact_count; i++) { artifact_type *a_ptr = &a_info[i]; /*hack - if a new "normal artifact has been added in mid-game, don't erase it*/ if ((i >= art_norm_count) && (i < z_info->art_norm_max)) continue; rd_string (a_ptr->name, MAX_LEN_ART_NAME); rd_byte(&a_ptr->tval); rd_byte(&a_ptr->sval); rd_s16b(&a_ptr->pval); rd_s16b(&a_ptr->to_h); rd_s16b(&a_ptr->to_d); rd_s16b(&a_ptr->to_a); rd_s16b(&a_ptr->ac); rd_byte(&a_ptr->dd); rd_byte(&a_ptr->ds); rd_s16b(&a_ptr->weight); rd_s32b(&a_ptr->cost); rd_u32b(&a_ptr->a_flags1); rd_u32b(&a_ptr->a_flags2); rd_u32b(&a_ptr->a_flags3); rd_u32b(&a_ptr->a_native); rd_byte(&a_ptr->a_level); rd_byte(&a_ptr->a_rarity); rd_byte(&a_ptr->activation); rd_u16b(&a_ptr->time); rd_u16b(&a_ptr->randtime); } } else { /* Strip the the artifacts for a dead/new character*/ for (i = begin; i < artifact_count; i++) { char tmpstr[MAX_LEN_ART_NAME]; rd_string (tmpstr, sizeof (tmpstr)); /*a_ptr->name*/ rd_byte(&tmp8u); /* a_ptr->tval */ rd_byte(&tmp8u); /* a_ptr->sval */ rd_s16b(&tmp16s); /* a_ptr->pval */ rd_s16b(&tmp16s); /* a_ptr->to_h */ rd_s16b(&tmp16s); /* a_ptr->to_d */ rd_s16b(&tmp16s); /* a_ptr->to_a */ rd_s16b(&tmp16s); /* a_ptr->ac */ rd_byte(&tmp8u); /* a_ptr->dd */ rd_byte(&tmp8u); /* a_ptr->ds */ rd_s16b(&tmp16s); /* a_ptr->weight */ rd_s32b(&tmp32s); /* a_ptr->cost */ rd_u32b(&tmp32u); /* a_ptr->flags1 */ rd_u32b(&tmp32u); /* a_ptr->flags2 */ rd_u32b(&tmp32u); /* a_ptr->flags3 */ rd_u32b(&tmp32u); /* a_ptr->a_native */ rd_byte(&tmp8u); /* a_ptr->level */ rd_byte(&tmp8u); /* a_ptr->rarity */ rd_byte(&tmp8u); /* a_ptr->activation */ rd_u16b(&tmp16u); /* a_ptr->time */ rd_u16b(&tmp16u); /* a_ptr->randtime */ } } return (0); }
/* * Read the "extra" information */ static errr rd_extra(void) { int i, j; byte tmp8u; u16b file_e_max; rd_string(op_ptr->full_name, sizeof(op_ptr->full_name)); rd_string(p_ptr->died_from, 80); rd_string(p_ptr->history, 250); /* Player race */ rd_byte(&p_ptr->prace); /* Verify player race */ if (p_ptr->prace >= z_info->p_max) { note(format("Invalid player race (%d).", p_ptr->prace)); return (-1); } /* Player house */ rd_byte(&p_ptr->phouse); /* Verify player house */ if (p_ptr->phouse >= z_info->c_max) { note(format("Invalid player house (%d).", p_ptr->phouse)); return (-1); } /* Player sex */ rd_byte(&p_ptr->psex); /* Tutorial? */ rd_s16b(&p_ptr->game_type); /* Age/Height/Weight */ rd_s16b(&p_ptr->age); rd_s16b(&p_ptr->ht); rd_s16b(&p_ptr->wt); /* Read the stat info */ for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_base[i]); for (i = 0; i < A_MAX; i++) rd_s16b(&p_ptr->stat_drain[i]); /* Read the skill info */ for (i = 0; i < S_MAX; i++) rd_s16b(&p_ptr->skill_base[i]); /* Read the abilities info */ for (i = 0; i < S_MAX; i++) { for (j = 0; j < ABILITIES_MAX; j++) { rd_byte(&p_ptr->innate_ability[i][j]); rd_byte(&p_ptr->active_ability[i][j]); } } rd_s16b(&p_ptr->last_attack_m_idx); rd_s16b(&p_ptr->consecutive_attacks); rd_s16b(&p_ptr->bane_type); for (i = 0; i < ACTION_MAX; ++i) { rd_byte(&(p_ptr->previous_action[i])); } rd_byte(&p_ptr->focused); rd_s32b(&p_ptr->new_exp); rd_s32b(&p_ptr->exp); rd_s32b(&p_ptr->encounter_exp); rd_s32b(&p_ptr->kill_exp); rd_s32b(&p_ptr->descent_exp); rd_s32b(&p_ptr->ident_exp); rd_s16b(&p_ptr->mhp); rd_s16b(&p_ptr->chp); rd_u16b(&p_ptr->chp_frac); rd_s16b(&p_ptr->msp); rd_s16b(&p_ptr->csp); rd_u16b(&p_ptr->csp_frac); rd_s16b(&p_ptr->max_depth); /* Hack -- Repair maximum dungeon level */ if (p_ptr->max_depth < 0) p_ptr->max_depth = 1; rd_u16b(&p_ptr->staircasiness); /* More info */ rd_s16b(&p_ptr->sc); /* Read the flags */ rd_byte(&p_ptr->song1); rd_byte(&p_ptr->song2); rd_s16b(&p_ptr->song_duration); rd_s16b(&p_ptr->wrath); rd_s16b(&p_ptr->blind); rd_s16b(&p_ptr->entranced); rd_s16b(&p_ptr->confused); rd_s16b(&p_ptr->food); rd_u16b(&p_ptr->stairs_taken); rd_u16b(&p_ptr->forge_drought); rd_u16b(&p_ptr->forge_count); rd_s16b(&p_ptr->energy); rd_s16b(&p_ptr->fast); rd_s16b(&p_ptr->slow); rd_s16b(&p_ptr->afraid); rd_s16b(&p_ptr->cut); rd_s16b(&p_ptr->stun); rd_s16b(&p_ptr->poisoned); rd_s16b(&p_ptr->image); rd_s16b(&p_ptr->rage); rd_s16b(&p_ptr->tmp_str); rd_s16b(&p_ptr->tmp_dex); rd_s16b(&p_ptr->tmp_con); rd_s16b(&p_ptr->tmp_gra); rd_s16b(&p_ptr->tim_invis); rd_s16b(&p_ptr->word_recall); rd_s16b(&p_ptr->darkened); rd_s16b(&p_ptr->oppose_fire); rd_s16b(&p_ptr->oppose_cold); rd_s16b(&p_ptr->oppose_pois); rd_byte(&p_ptr->stealth_mode); rd_byte(&p_ptr->self_made_arts); // 20 spare bytes strip_bytes(20); /* Read item-quality squelch sub-menu */ for (i = 0; i < SQUELCH_BYTES; i++) rd_byte(&squelch_level[i]); /* Load the name of the current greater vault */ rd_string(g_vault_name, sizeof(g_vault_name)); /* Read the number of saved special item types */ rd_u16b(&file_e_max); /* Read special item squelch settings */ for (i = 0; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; tmp8u = 0; if (i < file_e_max) rd_byte(&tmp8u); e_ptr->squelch |= (tmp8u & 0x01); e_ptr->everseen |= (tmp8u & 0x02); e_ptr->aware |= (tmp8u & 0x04); /* Hack - Repair the savefile */ if (!e_ptr->everseen) e_ptr->squelch = FALSE; } /* Read possible extra elements */ while (i < file_e_max) { rd_byte(&tmp8u); i++; } /*Write the current number of auto-inscriptions*/ rd_u16b(&inscriptionsCount); /*Write the autoinscriptions array*/ for(i = 0; i < inscriptionsCount; i++) { char tmp[80]; rd_s16b(&inscriptions[i].kindIdx); rd_string(tmp, 80); inscriptions[i].inscriptionIdx = quark_add(tmp); } for (i = 0; i < MAX_GREATER_VAULTS; i++) { s16b n; rd_s16b(&n); p_ptr->greater_vaults[i] = n; } /* Read the randart version */ rd_u32b(&randart_version); /* Read the randart seed */ rd_u32b(&seed_randart); /* Hack -- the two "special seeds" */ rd_u32b(&seed_flavor); /* Special stuff */ rd_u16b(&p_ptr->panic_save); rd_byte(&p_ptr->truce); rd_byte(&p_ptr->morgoth_hits); rd_byte(&p_ptr->crown_hint); rd_byte(&p_ptr->crown_shatter); rd_byte(&p_ptr->cursed); rd_byte(&p_ptr->on_the_run); rd_byte(&p_ptr->morgoth_slain); rd_u16b(&p_ptr->escaped); rd_u16b(&p_ptr->noscore); rd_s16b(&p_ptr->smithing_leftover); rd_byte(&tmp8u); p_ptr->unique_forge_made = tmp8u; rd_byte(&tmp8u); p_ptr->unique_forge_seen = tmp8u; /* Read "death" */ rd_byte(&tmp8u); p_ptr->is_dead = tmp8u; /* Read "feeling" */ rd_byte(&tmp8u); feeling = tmp8u; /*read the level feeling*/ rd_byte(&tmp8u); do_feeling = tmp8u; /* Current turn */ rd_s32b(&turn); /* Current player turn */ rd_s32b(&playerturn); return (0); }
/* * Read an object * * This function attempts to "repair" old savefiles, and to extract * the most up to date values for various object fields. */ static errr rd_item(object_type *o_ptr) { u32b f1, f2, f3; object_kind *k_ptr; char buf[128]; int i; /* Kind */ rd_s16b(&o_ptr->k_idx); /* Paranoia */ if ((o_ptr->k_idx < 0) || (o_ptr->k_idx >= z_info->k_max)) { return (-1); } /* Hallucinatory Kind */ rd_s16b(&o_ptr->image_k_idx); /* Location */ rd_byte(&o_ptr->iy); rd_byte(&o_ptr->ix); /* Type/Subtype */ rd_byte(&o_ptr->tval); rd_byte(&o_ptr->sval); /* Special pval */ rd_s16b(&o_ptr->pval); rd_byte(&o_ptr->discount); rd_byte(&o_ptr->number); rd_s16b(&o_ptr->weight); rd_byte(&o_ptr->name1); rd_byte(&o_ptr->name2); rd_s16b(&o_ptr->timeout); rd_s16b(&o_ptr->att); rd_byte(&o_ptr->dd); rd_byte(&o_ptr->ds); rd_s16b(&o_ptr->evn); rd_byte(&o_ptr->pd); rd_byte(&o_ptr->ps); rd_byte(&o_ptr->pickup); rd_u32b(&o_ptr->ident); rd_byte(&o_ptr->marked); /* Monster holding object */ rd_s16b(&o_ptr->held_m_idx); /* Special powers */ rd_byte(&o_ptr->xtra1); // granted abilities rd_byte(&o_ptr->abilities); for (i = 0; i < 8; i++) { rd_byte(&o_ptr->skilltype[i]); rd_byte(&o_ptr->abilitynum[i]); } // 8 spare bytes strip_bytes(8); /* Inscription */ rd_string(buf, sizeof(buf)); /* Save the inscription */ if (buf[0]) o_ptr->obj_note = quark_add(buf); /* Obtain the "kind" template */ k_ptr = &k_info[o_ptr->k_idx]; /* Obtain tval/sval from k_info */ o_ptr->tval = k_ptr->tval; o_ptr->sval = k_ptr->sval; /* Hack -- notice "broken" items */ if (k_ptr->cost <= 0) o_ptr->ident |= (IDENT_BROKEN); /* Repair non "wearable" items */ if (!wearable_p(o_ptr)) { /* Get the correct fields */ o_ptr->att = k_ptr->att; o_ptr->evn = k_ptr->evn; /* Get the correct fields */ o_ptr->dd = k_ptr->dd; o_ptr->ds = k_ptr->ds; o_ptr->pd = k_ptr->pd; o_ptr->ps = k_ptr->ps; /* Get the correct weight */ o_ptr->weight = k_ptr->weight; /* Paranoia */ o_ptr->name1 = o_ptr->name2 = 0; /* All done */ return (0); } /* Extract the flags */ object_flags(o_ptr, &f1, &f2, &f3); /* Paranoia */ if (o_ptr->name1) { artefact_type *a_ptr; /*hack - adjust if new artefact*/ if (o_ptr->name1 >= art_norm_count) { o_ptr->name1 += new_artefacts; } /* Paranoia */ if (o_ptr->name1 >= z_info->art_max) { return (-1); } /* Obtain the artefact info */ a_ptr = &a_info[o_ptr->name1]; /* Verify that artefact */ if (a_ptr->tval + a_ptr->sval == 0) { o_ptr->name1 = 0; } } /* Paranoia */ if (o_ptr->name2) { ego_item_type *e_ptr; /* Paranoia */ if (o_ptr->name2 >= z_info->e_max) { return (-1); } /* Obtain the special item info */ e_ptr = &e_info[o_ptr->name2]; /* Verify that special item */ if (!e_ptr->name) o_ptr->name2 = 0; } /* Hack -- extract the "broken" flag */ if (o_ptr->pval < 0) o_ptr->ident |= (IDENT_BROKEN); /* Artefacts */ if (o_ptr->name1) { artefact_type *a_ptr; /* Obtain the artefact info */ a_ptr = &a_info[o_ptr->name1]; /* Get the new artefact "pval" */ o_ptr->pval = a_ptr->pval; /* Get the new artefact fields */ o_ptr->dd = a_ptr->dd; o_ptr->ds = a_ptr->ds; o_ptr->pd = a_ptr->pd; o_ptr->ps = a_ptr->ps; o_ptr->evn = a_ptr->evn; /* Get the new artefact weight */ o_ptr->weight = a_ptr->weight; /* Hack -- extract the "broken" flag */ if (!a_ptr->cost) o_ptr->ident |= (IDENT_BROKEN); } /* Ego items */ if (o_ptr->name2) { ego_item_type *e_ptr; /* Obtain the special item info */ e_ptr = &e_info[o_ptr->name2]; /* Hack -- extract the "broken" flag */ if (!e_ptr->cost) o_ptr->ident |= (IDENT_BROKEN); /* Hack -- enforce legal pval */ if (e_ptr->flags1 & (TR1_PVAL_MASK)) { /* Force a meaningful pval */ if (!o_ptr->pval) o_ptr->pval = 1; } } /* Used to add back boosted damage dice and sides */ /* No longer needed as we don't repair non-artefacts anymore */ /* Success */ return (0); }
/* * Read the dungeon * * The monsters/objects must be loaded in the same order * that they were stored, since the actual indexes matter. * * Note that the size of the dungeon is now hard-coded to * DUNGEON_HGT by DUNGEON_WID, and any dungeon with another * size will be silently discarded by this routine. * * Note that dungeon objects, including objects held by monsters, are * placed directly into the dungeon, using "object_copy()", which will * copy "iy", "ix", and "held_m_idx", leaving "next_o_idx" blank for * objects held by monsters, since it is not saved in the savefile. * * After loading the monsters, the objects being held by monsters are * linked directly into those monsters. */ static errr rd_dungeon(void) { int i, y, x; s16b depth; s16b py, px; byte count; byte tmp8u; u16b limit; /*** Basic info ***/ /* Header info */ rd_s16b(&depth); rd_s16b(&py); rd_s16b(&px); rd_byte(&p_ptr->cur_map_hgt); rd_byte(&p_ptr->cur_map_wid); /* Ignore illegal dungeons */ if ((depth < 0) || (depth > MORGOTH_DEPTH)) { note(format("Ignoring illegal dungeon depth (%d)", depth)); return (0); } /* Ignore illegal dungeons */ if ((p_ptr->cur_map_hgt > MAX_DUNGEON_HGT) || (p_ptr->cur_map_wid > MAX_DUNGEON_WID)) { /* XXX XXX XXX */ note(format("Ignoring illegal dungeon size (%d,%d).", p_ptr->cur_map_hgt, p_ptr->cur_map_wid)); return (0); } /* Ignore illegal dungeons */ if ((px < 0) || (px >= p_ptr->cur_map_wid) || (py < 0) || (py >= p_ptr->cur_map_hgt)) { note(format("Ignoring illegal player location (%d,%d).", py, px)); return (1); } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < p_ptr->cur_map_hgt; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Extract "info" */ cave_info[y][x] = tmp8u; /* Advance/Wrap */ if (++x >= p_ptr->cur_map_wid) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= p_ptr->cur_map_hgt) break; } } } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < p_ptr->cur_map_hgt; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Extract "feat" */ cave_set_feat(y, x, tmp8u); /* Advance/Wrap */ if (++x >= p_ptr->cur_map_wid) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= p_ptr->cur_map_hgt) break; } } } /*** Player ***/ /* Load depth */ p_ptr->depth = depth; /* Place player in dungeon */ if (!player_place(py, px)) { note(format("Cannot place player (%d,%d)!", py, px)); return (-1); } /*** Objects ***/ /* Read the item count */ rd_u16b(&limit); /* Verify maximum */ if (limit > z_info->o_max) { note(format("Too many (%d) object entries!", limit)); return (-1); } /* Read the dungeon items */ for (i = 1; i < limit; i++) { object_type *i_ptr; object_type object_type_body; s16b o_idx; object_type *o_ptr; /* Get the object */ i_ptr = &object_type_body; /* Wipe the object */ object_wipe(i_ptr); /* Read the item */ if (rd_item(i_ptr)) { note("Error reading item"); return (-1); } /* Make an object */ o_idx = o_pop(); /* Paranoia */ if (o_idx != i) { note(format("Cannot place object %d!", i)); return (-1); } /* Get the object */ o_ptr = &o_list[o_idx]; /* Structure Copy */ object_copy(o_ptr, i_ptr); /* Dungeon floor */ if (!i_ptr->held_m_idx) { int x = i_ptr->ix; int y = i_ptr->iy; /* ToDo: Verify coordinates */ /* Link the object to the pile */ o_ptr->next_o_idx = cave_o_idx[y][x]; /* Link the floor to the object */ cave_o_idx[y][x] = o_idx; /* Rearrange stack if needed */ rearrange_stack(y, x); } } /*** Monsters ***/ /* Read the monster count */ rd_u16b(&limit); /* Hack -- verify */ if (limit > z_info->m_max) { note(format("Too many (%d) monster entries!", limit)); return (-1); } /* Read the monsters */ for (i = 1; i < limit; i++) { monster_type *n_ptr; monster_type monster_type_body; monster_race *r_ptr; int r_idx; /* Get local monster */ n_ptr = &monster_type_body; /* Clear the monster */ (void)WIPE(n_ptr, monster_type); /* Read the monster */ rd_monster(n_ptr); /* Access the "r_idx" of the chosen monster */ r_idx = n_ptr->r_idx; /* Access the actual race */ r_ptr = &r_info[r_idx]; /* Place monster in dungeon */ if (monster_place(n_ptr->fy, n_ptr->fx, n_ptr) != i) { note(format("Cannot place monster %d", i)); return (-1); } } /*** Holding ***/ /* Reacquire objects */ for (i = 1; i < o_max; ++i) { object_type *o_ptr; monster_type *m_ptr; /* Get the object */ o_ptr = &o_list[i]; /* Ignore dungeon objects */ if (!o_ptr->held_m_idx) continue; /* Verify monster index */ if (o_ptr->held_m_idx > z_info->m_max) { note("Invalid monster index"); return (-1); } /* Get the monster */ m_ptr = &mon_list[o_ptr->held_m_idx]; /* Link the object to the pile */ o_ptr->next_o_idx = m_ptr->hold_o_idx; /* Link the monster to the object */ m_ptr->hold_o_idx = i; } // dump the wandering monster information for (i = FLOW_WANDERING_HEAD; i < MAX_FLOWS; i++) { rd_byte(&flow_center_y[i]); rd_byte(&flow_center_x[i]); rd_s16b(&wandering_pause[i]); update_noise(flow_center_y[i], flow_center_x[i], i); } /*** Success ***/ /* The dungeon is ready */ character_dungeon = TRUE; /* Success */ return (0); }
/** * Read an object. */ static struct object *rd_item(void) { struct object *obj = object_new(); byte tmp8u; u16b tmp16u; byte effect; size_t i; char buf[128]; byte ver = 1; rd_u16b(&tmp16u); rd_byte(&ver); if (tmp16u != 0xffff) return NULL; rd_u16b(&obj->oidx); /* Location */ rd_byte(&obj->iy); rd_byte(&obj->ix); /* Type/Subtype */ rd_string(buf, sizeof(buf)); if (buf[0]) { obj->tval = tval_find_idx(buf); } rd_string(buf, sizeof(buf)); if (buf[0]) { obj->sval = lookup_sval(obj->tval, buf); } rd_s16b(&obj->pval); rd_byte(&obj->number); rd_s16b(&obj->weight); rd_string(buf, sizeof(buf)); if (buf[0]) { obj->artifact = lookup_artifact_name(buf); if (!obj->artifact) { note(format("Couldn't find artifact %s!", buf)); return NULL; } } rd_string(buf, sizeof(buf)); if (buf[0]) { obj->ego = lookup_ego_item(buf, obj->tval, obj->sval); if (!obj->ego) { note(format("Couldn't find ego item %s!", buf)); return NULL; } } rd_byte(&effect); rd_s16b(&obj->timeout); rd_s16b(&obj->to_h); rd_s16b(&obj->to_d); rd_s16b(&obj->to_a); rd_s16b(&obj->ac); rd_byte(&obj->dd); rd_byte(&obj->ds); rd_byte(&obj->origin); rd_byte(&obj->origin_depth); rd_string(buf, sizeof(buf)); if (buf[0]) { obj->origin_race = lookup_monster(buf); } rd_byte(&obj->notice); for (i = 0; i < of_size; i++) rd_byte(&obj->flags[i]); for (i = 0; i < obj_mod_max; i++) { rd_s16b(&obj->modifiers[i]); } /* Read brands */ rd_byte(&tmp8u); if (tmp8u) { obj->brands = mem_zalloc(z_info->brand_max * sizeof(bool)); for (i = 0; i < brand_max; i++) { rd_byte(&tmp8u); obj->brands[i] = tmp8u ? true : false; } } /* Read slays */ rd_byte(&tmp8u); if (tmp8u) { obj->slays = mem_zalloc(z_info->slay_max * sizeof(bool)); for (i = 0; i < slay_max; i++) { rd_byte(&tmp8u); obj->slays[i] = tmp8u ? true : false; } } /* Read curses */ rd_byte(&tmp8u); if (tmp8u) { obj->curses = mem_zalloc(z_info->curse_max * sizeof(struct curse_data)); for (i = 0; i < curse_max; i++) { rd_byte(&tmp8u); obj->curses[i].power = tmp8u; rd_u16b(&tmp16u); obj->curses[i].timeout = tmp16u; } } for (i = 0; i < elem_max; i++) { rd_s16b(&obj->el_info[i].res_level); rd_byte(&obj->el_info[i].flags); } /* Monster holding object */ rd_s16b(&obj->held_m_idx); rd_s16b(&obj->mimicking_m_idx); /* Activation */ rd_u16b(&tmp16u); if (tmp16u) obj->activation = &activations[tmp16u]; rd_u16b(&tmp16u); obj->time.base = tmp16u; rd_u16b(&tmp16u); obj->time.dice = tmp16u; rd_u16b(&tmp16u); obj->time.sides = tmp16u; /* Save the inscription */ rd_string(buf, sizeof(buf)); if (buf[0]) obj->note = quark_add(buf); /* Lookup item kind */ obj->kind = lookup_kind(obj->tval, obj->sval); /* Check we have a kind */ if ((!obj->tval && !obj->sval) || !obj->kind) { object_delete(&obj); return NULL; } /* Set effect */ if (effect && obj->ego) obj->effect = obj->ego->effect; if (effect && !obj->effect) obj->effect = obj->kind->effect; /* Success */ return obj; }
/** * Read a monster */ static bool rd_monster(struct chunk *c, struct monster *mon) { byte tmp8u; u16b tmp16u; char race_name[80]; size_t j; /* Read the monster race */ rd_string(race_name, sizeof(race_name)); mon->race = lookup_monster(race_name); if (!mon->race) { note(format("Monster race %s no longer exists!", race_name)); return (-1); } /* Read the other information */ rd_byte(&mon->fy); rd_byte(&mon->fx); rd_s16b(&mon->hp); rd_s16b(&mon->maxhp); rd_byte(&mon->mspeed); rd_byte(&mon->energy); rd_byte(&tmp8u); for (j = 0; j < tmp8u; j++) rd_s16b(&mon->m_timed[j]); /* Read and extract the flag */ for (j = 0; j < mflag_size; j++) rd_byte(&mon->mflag[j]); for (j = 0; j < of_size; j++) rd_byte(&mon->known_pstate.flags[j]); for (j = 0; j < elem_max; j++) rd_s16b(&mon->known_pstate.el_info[j].res_level); rd_u16b(&tmp16u); if (tmp16u) { /* Find and set the mimicked object */ struct object *square_obj = square_object(c, mon->fy, mon->fx); /* Try and find the mimicked object; if we fail, create a new one */ while (square_obj) { if (square_obj->mimicking_m_idx == tmp16u) break; square_obj = square_obj->next; } if (square_obj) { mon->mimicked_obj = square_obj; } else { mon_create_mimicked_object(c, mon, tmp16u); } } /* Read all the held objects (order is unimportant) */ while (true) { struct object *obj = rd_item(); if (!obj) break; pile_insert(&mon->held_obj, obj); assert(obj->oidx); assert(c->objects[obj->oidx] == NULL); c->objects[obj->oidx] = obj; } return true; }