/* * Read a store */ static errr rd_store(int n) { store_type *st_ptr = &store[n]; int j; byte own, num; /* Read the basic info */ rd_s32b(&st_ptr->store_open); rd_s16b(&st_ptr->insult_cur); rd_byte(&own); rd_byte(&num); rd_s16b(&st_ptr->good_buy); rd_s16b(&st_ptr->bad_buy); /* Paranoia */ if (own >= z_info->b_max) { note("Illegal store owner!"); return (-1); } st_ptr->owner = own; /* Read the items */ for (j = 0; j < num; j++) { object_type *i_ptr; object_type object_type_body; /* Get local 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); } /* Accept any valid items */ if (st_ptr->stock_num < STORE_INVEN_MAX) { int k = st_ptr->stock_num++; /* Accept the item */ object_copy(&st_ptr->stock[k], i_ptr); } } /* Success */ return (0); }
/* * Read a store */ static errr rd_store(int town_number, int store_number) { store_type *st_ptr = &town[town_number].store[store_number]; int j; byte num; s16b tmp16s; /* Read the basic info */ rd_s32b(&st_ptr->store_open); rd_s16b(&tmp16s); rd_byte(&st_ptr->owner); rd_byte(&num); rd_s16b(&tmp16s); rd_s16b(&tmp16s); /* Read last visit */ rd_s32b(&st_ptr->last_visit); /* Read the items */ for (j = 0; j < num; j++) { object_type forge; object_type *q_ptr; /* Get local object */ q_ptr = &forge; /* Wipe the object */ object_wipe(q_ptr); /* Read the item */ rd_item(q_ptr); /* Acquire valid items */ if (st_ptr->stock_num < (store_number == STORE_HOME ? (STORE_INVEN_MAX) * 10 : STORE_INVEN_MAX)) { int k = st_ptr->stock_num; if (q_ptr->k_idx != 0) { /* Acquire the item */ object_copy(&st_ptr->stock[k], q_ptr); st_ptr->stock_num++; } } } /* Success */ return (0); }
/* * Read a store */ static errr rd_store(int n) { store_type *st_ptr = &store[n]; int j; byte own, num; start_section_read("store"); /* Read the basic info */ read_hturn("store_open", &st_ptr->store_open); st_ptr->insult_cur = read_int("insult_cur"); own = read_int("owner"); num = read_int("stock_num"); st_ptr->good_buy = read_int("good_buy"); st_ptr->bad_buy = read_int("bad_buy"); /* Extract the owner (see above) */ st_ptr->owner = own; start_section_read("stock"); /* Read the items */ for (j = 0; j < num; j++) { object_type forge; /* Read the item */ rd_item(&forge); /* Acquire valid items */ if (st_ptr->stock_num < STORE_INVEN_MAX) { /* Acquire the item */ st_ptr->stock[st_ptr->stock_num++] = forge; } } end_section_read("stock"); end_section_read("store"); /* Success */ return (0); }
static int rd_objects(void) { int i; u16b limit; /* Only if the player's alive */ if (p_ptr->is_dead) return 0; /* 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; } } return 0; }
static int rd_stores(void) { int i; u16b tmp16u; /* Read the stores */ rd_u16b(&tmp16u); for (i = 0; i < tmp16u; i++) { store_type *st_ptr = &store[i]; int j; byte own, num; /* XXX */ strip_bytes(6); /* Read the basic info */ rd_byte(&own); rd_byte(&num); /* XXs */ strip_bytes(4); /* Paranoia */ if (own >= z_info->b_max) { note("Illegal store owner!"); return (-1); } st_ptr->owner = store_ownerbyidx(st_ptr, own); /* Read the items */ for (j = 0; j < num; j++) { object_type *i_ptr; object_type object_type_body; /* Get local 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); } i_ptr->ident |= IDENT_STORE; /* Accept any valid items */ if ((st_ptr->stock_num < STORE_INVEN_MAX) && (i_ptr->k_idx)) { int k = st_ptr->stock_num++; /* Accept the item */ object_copy(&st_ptr->stock[k], i_ptr); } } } return 0; }
/* * Read the player inventory * * Note that the inventory is "re-sorted" later by "dungeon()". */ static int rd_inventory(void) { int slot = 0; object_type *i_ptr; object_type object_type_body; /* Read until done */ while (1) { u16b n; /* Get the next item index */ rd_u16b(&n); /* Nope, we reached the end */ if (n == 0xFFFF) break; /* Get local 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); } /* Hack -- verify item */ if (!i_ptr->k_idx) continue;; /* Verify slot */ if (n >= INVEN_TOTAL) return (-1); /* Wield equipment */ if (n >= INVEN_WIELD) { /* Copy object */ object_copy(&p_ptr->inventory[n], i_ptr); /* Add the weight */ p_ptr->total_weight += (i_ptr->number * i_ptr->weight); /* One more item */ p_ptr->equip_cnt++; } /* Warning -- backpack is full */ else if (p_ptr->inven_cnt == INVEN_PACK) { /* Oops */ note("Too many items in the inventory!"); /* Fail */ return (-1); } /* Carry inventory */ else { /* Get a slot */ n = slot++; /* Copy object */ object_copy(&p_ptr->inventory[n], i_ptr); /* Add the weight */ p_ptr->total_weight += (i_ptr->number * i_ptr->weight); /* One more item */ p_ptr->inven_cnt++; } } /* 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; int by, bx; s16b town; s16b dungeon; s16b depth; s16b py, px; s16b ymax, xmax; byte count; byte tmp8u; u16b tmp16u; u16b limit; /*** Basic info ***/ /* Header info */ rd_s16b(&depth); rd_s16b(&dungeon); rd_s16b(&py); rd_s16b(&px); rd_s16b(&ymax); rd_s16b(&xmax); rd_s16b(&town); rd_u16b(&tmp16u); /* Ignore illegal dungeons */ if (town>=z_info->t_max) { note(format("Ignoring illegal dungeon (%d)", dungeon)); return (0); } /* Ignore illegal dungeons */ if ((depth < 0) || (depth > max_depth(dungeon))) { note(format("Ignoring illegal dungeon depth (%d)", depth)); return (0); } /* Ignore illegal dungeons */ if ((ymax != DUNGEON_HGT) || (xmax != DUNGEON_WID)) { /* XXX XXX XXX */ note(format("Ignoring illegal dungeon size (%d,%d).", ymax, xmax)); return (0); } /* Ignore illegal dungeons */ if ((px < 0) || (px >= DUNGEON_WID) || (py < 0) || (py >= DUNGEON_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 < DUNGEON_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 >= DUNGEON_WID) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= DUNGEON_HGT) break; } } } /* Hack -- not fully dynamic */ dyna_full = FALSE; /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < DUNGEON_HGT; ) { /* Grab RLE info */ rd_byte(&count); if (variant_save_feats) rd_u16b(&tmp16u); else rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Save the feat */ if (variant_save_feats) cave_feat[y][x] = tmp16u; else cave_feat[y][x] = tmp8u; /* Check for los flag set*/ if (f_info[cave_feat[y][x]].flags1 & (FF1_LOS)) { cave_info[y][x] &= ~(CAVE_WALL); } /* Handle wall grids */ else { cave_info[y][x] |= (CAVE_WALL); } /* Handle dynamic grids */ if (f_info[cave_feat[y][x]].flags3 & (FF3_DYNAMIC_MASK)) { if (dyna_n < (DYNA_MAX-1)) { dyna_g[dyna_n++] = GRID(y,x); } else { dyna_full = TRUE; dyna_cent_y = 255; dyna_cent_x = 255; } } /* Advance/Wrap */ if (++x >= DUNGEON_WID) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= DUNGEON_HGT) break; } } } /*** Player ***/ /* Fix depth */ if (depth < 1) depth = min_depth(dungeon); /* Fix depth */ if (depth > max_depth(dungeon)) depth = max_depth(dungeon); /* Load depth */ p_ptr->depth = depth; p_ptr->dungeon = dungeon; p_ptr->town = town; /* Place player in dungeon */ if (!player_place(py, px)) { note(format("Cannot place player (%d,%d)!", py, px)); return (-1); } /*** Room descriptions ***/ if (!variant_room_info) { /* Initialize the room table */ for (by = 0; by < MAX_ROOMS_ROW; by++) { for (bx = 0; bx < MAX_ROOMS_COL; bx++) { dun_room[by][bx] = 0; } } /* Initialise 'zeroeth' room description */ room_info[0].flags = 0; } else { for (bx = 0; bx < MAX_ROOMS_ROW; bx++) { for (by = 0; by < MAX_ROOMS_COL; by++) { rd_byte(&dun_room[bx][by]); } } for (i = 1; i < DUN_ROOMS; i++) { int j; rd_byte(&room_info[i].type); rd_byte(&room_info[i].flags); if (room_info[i].type == ROOM_NORMAL) { for (j = 0; j < ROOM_DESC_SECTIONS; j++) { rd_s16b(&room_info[i].section[j]); if (room_info[i].section[j] == -1) break; } } } } /*** 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; } } /*** 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; /* Get local monster */ n_ptr = &monster_type_body; /* Clear the monster */ (void)WIPE(n_ptr, monster_type); /* Read the monster */ rd_monster(n_ptr); /* 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 = &m_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; } /*** Success ***/ /* The dungeon is ready */ character_dungeon = TRUE; /* Regenerate town in post 2.9.3 versions */ if (older_than(2, 9, 4) && (p_ptr->depth == 0)) character_dungeon = FALSE; /* 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. */ static errr rd_dungeon(void) { int i, y, x; int ymax, xmax; byte count; byte tmp8u; s16b tmp16s; u16b limit; cave_type *c_ptr; /*** Basic info ***/ /* Header info */ rd_s16b(&dun_level); /* Set the base level for old versions */ base_level = dun_level; /* Read the base level */ rd_s16b(&base_level); rd_s16b(&num_repro); rd_s16b(&py); rd_s16b(&px); rd_s16b(&cur_hgt); rd_s16b(&cur_wid); rd_s16b(&tmp16s); /* max_panel_rows */ rd_s16b(&tmp16s); /* max_panel_cols */ /* Maximal size */ ymax = cur_hgt; xmax = cur_wid; /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < ymax; ) { /* Grab RLE info */ rd_byte(&count); rd_s16b(&tmp16s); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Access the cave */ c_ptr = &cave[y][x]; /* Extract "info" */ c_ptr->info = tmp16s; /* Decline invalid flags */ c_ptr->info &= ~(CAVE_LITE | CAVE_VIEW | CAVE_MNLT); /* Advance/Wrap */ if (++x >= xmax) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= ymax) break; } } } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < ymax; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Access the cave */ c_ptr = &cave[y][x]; /* Extract "feat" */ c_ptr->feat = tmp8u; /* Advance/Wrap */ if (++x >= xmax) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= ymax) break; } } } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < ymax; ) { /* Grab RLE info */ rd_byte(&count); rd_byte(&tmp8u); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Access the cave */ c_ptr = &cave[y][x]; /* Extract "feat" */ c_ptr->mimic = tmp8u; /* Advance/Wrap */ if (++x >= xmax) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= ymax) break; } } } /*** Run length decoding ***/ /* Load the dungeon data */ for (x = y = 0; y < ymax; ) { /* Grab RLE info */ rd_byte(&count); rd_s16b(&tmp16s); /* Apply the RLE info */ for (i = count; i > 0; i--) { /* Access the cave */ c_ptr = &cave[y][x]; /* Extract "feat" */ c_ptr->special = tmp16s; /* Advance/Wrap */ if (++x >= xmax) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= ymax) break; } } } /*** Objects ***/ /* Read the item count */ rd_u16b(&limit); /* Verify maximum */ if (limit > max_o_idx) { #ifdef JP note(format("アイテムの配列が大きすぎる(%d)!", limit)); #else note(format("Too many (%d) object entries!", limit)); #endif return (151); } /* Read the dungeon items */ for (i = 1; i < limit; i++) { int o_idx; object_type *o_ptr; /* Get a new record */ o_idx = o_pop(); /* Oops */ if (i != o_idx) { #ifdef JP note(format("アイテム配置エラー (%d <> %d)", i, o_idx)); #else note(format("Object allocation error (%d <> %d)", i, o_idx)); #endif return (152); } /* Acquire place */ o_ptr = &o_list[o_idx]; /* Read the item */ rd_item(o_ptr); /* XXX XXX XXX XXX XXX */ /* Monster */ if (o_ptr->held_m_idx) { monster_type *m_ptr; /* Monster */ m_ptr = &m_list[o_ptr->held_m_idx]; /* Build a stack */ o_ptr->next_o_idx = m_ptr->hold_o_idx; /* Place the object */ m_ptr->hold_o_idx = o_idx; } /* Dungeon */ else { /* Access the item location */ c_ptr = &cave[o_ptr->iy][o_ptr->ix]; /* Build a stack */ o_ptr->next_o_idx = c_ptr->o_idx; /* Place the object */ c_ptr->o_idx = o_idx; } } /*** Monsters ***/ /* Read the monster count */ rd_u16b(&limit); /* Hack -- verify */ if (limit > max_m_idx) { #ifdef JP note(format("モンスターの配列が大きすぎる(%d)!", limit)); #else note(format("Too many (%d) monster entries!", limit)); #endif return (161); } /* Read the monsters */ for (i = 1; i < limit; i++) { int m_idx; monster_type *m_ptr; monster_race *r_ptr; /* Get a new record */ m_idx = m_pop(); /* Oops */ if (i != m_idx) { #ifdef JP note(format("モンスター配置エラー (%d <> %d)", i, m_idx)); #else note(format("Monster allocation error (%d <> %d)", i, m_idx)); #endif return (162); } /* Acquire monster */ m_ptr = &m_list[m_idx]; /* Read the monster */ rd_monster(m_ptr); /* Access grid */ c_ptr = &cave[m_ptr->fy][m_ptr->fx]; /* Mark the location */ c_ptr->m_idx = m_idx; /* Access race */ r_ptr = &r_info[m_ptr->r_idx]; /* Count XXX XXX XXX */ r_ptr->cur_num++; } /*** Success ***/ /* Regenerate the dungeon for corrupted panic-saves */ if ((py == 0) || (px == 0)) { character_dungeon = FALSE; } else { /* The dungeon is ready */ character_dungeon = TRUE; } /* Success */ return (0); }
/* * Read the player inventory * * Note that the inventory changed in Angband 2.7.4. Two extra * pack slots were added and the equipment was rearranged. Note * that these two features combine when parsing old save-files, in * which items from the old "aux" slot are "carried", perhaps into * one of the two new "inventory" slots. * * Note that the inventory is "re-sorted" later by "dungeon()". */ static errr rd_inventory(void) { int slot = 0; object_type forge; object_type *q_ptr; /* No weight */ p_ptr->total_weight = 0; /* No items */ inven_cnt = 0; equip_cnt = 0; /* Read until done */ while (1) { u16b n; /* Get the next item index */ rd_u16b(&n); /* Nope, we reached the end */ if (n == 0xFFFF) break; /* Get local object */ q_ptr = &forge; /* Wipe the object */ object_wipe(q_ptr); /* Read the item */ rd_item(q_ptr); /* Hack -- verify item */ if (!q_ptr->k_idx) return (53); /* Wield equipment */ if (n >= INVEN_WIELD) { if (q_ptr->k_idx) { /* Player touches it */ q_ptr->marked |= OM_TOUCHED; /* Copy object */ object_copy(&inventory[n], q_ptr); /* Add the weight */ p_ptr->total_weight += (q_ptr->number * q_ptr->weight); /* One more item */ equip_cnt++; } } /* Warning -- backpack is full */ else if (inven_cnt == INVEN_PACK) { /* Oops */ #ifdef JP note("持ち物の中のアイテムが多すぎる!"); #else note("Too many items in the inventory!"); #endif /* Fail */ return (54); } /* Carry inventory */ else { if (q_ptr->k_idx) { /* Get a slot */ n = slot++; /* Player touches it */ q_ptr->marked |= OM_TOUCHED; /* Copy object */ object_copy(&inventory[n], q_ptr); /* Add the weight */ p_ptr->total_weight += (q_ptr->number * q_ptr->weight); /* One more item */ inven_cnt++; } } } /* 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 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 player inventory * * Note that the inventory is "re-sorted" later by "dungeon()". */ static errr rd_inventory(void) { int slot = 0; object_type *i_ptr; object_type object_type_body; /* Read until done */ while (1) { u16b n; /* Get the next item index */ rd_u16b(&n); /* Nope, we reached the end */ if (n == 0xFFFF) break; /* Get local 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); } /* Hack -- verify item */ if (!i_ptr->k_idx) return (-1); /* Verify slot */ if (n >= ALL_INVEN_TOTAL) return (-1); /* Wield equipment */ if (n >= INVEN_WIELD) { /* Copy object */ object_copy(&inventory[n], i_ptr); /* One more item */ if (!IS_QUIVER_SLOT(n)) p_ptr->equip_cnt++; } /* Warning -- backpack is full */ else if (p_ptr->inven_cnt == INVEN_PACK) { /* Oops */ note("Too many items in the inventory!"); /* Fail */ return (-1); } /* Carry inventory */ else { /* Get a slot */ n = slot++; /* Copy object */ object_copy(&inventory[n], i_ptr); /* One more item */ p_ptr->inven_cnt++; } /* Update "p_ptr->pack_size_reduce" */ save_quiver_size(); } /* 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); }
errr rd_server_savefile() { int i; errr err = 0; char savefile[1024]; byte tmp8u; u16b tmp16u; u32b tmp32u; s32b tmp32s; int major; char name[80]; /* Savefile name */ path_build(savefile, 1024, ANGBAND_DIR_SAVE, "server"); /* The server savefile is a binary file */ file_handle = my_fopen(savefile, "r"); line_counter = 0; start_section_read("mangband_server_save"); start_section_read("version"); major = read_int("major"); major = read_int("minor"); major = read_int("patch"); end_section_read("version"); /* Paranoia */ if (!file_handle) return (-1); /* Clear the checksums */ v_check = 0L; x_check = 0L; /* Operating system info */ sf_xtra = read_uint("xtra"); /* Time of savefile creation */ sf_when = read_uint("timestamp"); /* Number of lives */ sf_lives = read_int("sf_lives"); /* Number of times played */ sf_saves = read_int("sf_saves"); /* Monster Memory */ start_section_read("monster_lore"); tmp16u = read_int("max_r_idx"); /* Incompatible save files */ if (tmp16u > z_info->r_max) { note(format("Too many (%u) monster races!", tmp16u)); return (21); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { monster_race *r_ptr; /* Read the lore */ rd_u_lore(i); /* Access the monster race */ r_ptr = &r_info[i]; } end_section_read("monster_lore"); /* Load the Artifacts */ start_section_read("artifacts"); tmp16u = read_int("max_a_idx"); /* Incompatible save files */ if (tmp16u > z_info->a_max) { note(format("Too many (%u) artifacts!", tmp16u)); return (24); } /* Read the artifact flags */ for (i = 0; i < tmp16u; i++) { tmp8u = read_int("artifact"); a_info[i].cur_num = tmp8u; } end_section_read("artifacts"); /* Read the stores */ start_section_read("stores"); tmp16u = read_int("max_stores"); for (i = 0; i < tmp16u; i++) { if (rd_store(i)) return (22); } end_section_read("stores"); /* Read party info if savefile is new enough */ start_section_read("parties"); tmp16u = read_int("max_parties"); /* Incompatible save files */ if (tmp16u > MAX_PARTIES) { note(format("Too many (%u) parties!", tmp16u)); return (25); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { rd_party(i); } end_section_read("parties"); /* XXX If new enough, read in the saved levels and monsters. */ start_section_read("dungeon_levels"); /* read the number of levels to be loaded */ tmp32u = read_uint("num_levels"); /* load the levels */ for (i = 0; i < tmp32u; i++) rd_dungeon(FALSE, 0); /* load any special static levels */ rd_dungeon_special(); end_section_read("dungeon_levels"); start_section_read("monsters"); /* get the number of monsters to be loaded */ tmp32u = read_int("max_monsters"); if (tmp32u > MAX_M_IDX) { note(format("Too many (%u) monsters!", tmp16u)); return (29); } /* load the monsters */ for (i = 1; i < tmp32u; i++) { rd_monster(&m_list[m_pop()]); } end_section_read("monsters"); /* Read object info */ start_section_read("objects"); tmp16u = read_int("max_objects"); /* Incompatible save files */ if (tmp16u > MAX_O_IDX) { note(format("Too many (%u) objects!", tmp16u)); return (26); } /* Read the available records */ for (i = 1; i < tmp16u; i++) { rd_item(&o_list[i]); } /* Set the maximum object number */ o_max = tmp16u; end_section_read("objects"); /* Read holding info */ /* 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 = &m_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; } /* Read house info */ start_section_read("houses"); tmp16u = read_int("num_houses"); /* Incompatible save files */ if (tmp16u > MAX_HOUSES) { note(format("Too many (%u) houses!", tmp16u)); return (27); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { rd_house(i); } num_houses = tmp16u; end_section_read("houses"); /* Read arenas info */ if (section_exists("arenas")) { start_section_read("arenas"); tmp16u = read_int("num_arenas"); /* Incompatible save files */ if (tmp16u > MAX_ARENAS) { note(format("Too many (%u) arenas!", tmp16u)); return (27); } /* Read the available records */ for (i = 0; i < tmp16u; i++) { rd_arena(i); } num_arenas = tmp16u; end_section_read("arenas"); } /* Read wilderness info */ start_section_read("wilderness"); /* read how many wilderness levels */ tmp32u = read_int("max_wild"); if (tmp32u > MAX_WILD) { note("Too many wilderness levels"); return 28; } for (i = 1; i < tmp32u; i++) { rd_wild(i); } end_section_read("wilderness"); /* Read the player name database */ start_section_read("player_names"); tmp32u = read_int("num_players"); /* Read the available records */ for (i = 0; i < tmp32u; i++) { start_section_read("player"); /* Read the ID */ tmp32s = read_int("id"); /* Read the player name */ read_str("name",name); /* Store the player name */ add_player_name(name, tmp32s); end_section_read("player"); } end_section_read("player_names"); seed_flavor = read_uint("seed_flavor"); seed_town = read_uint("seed_town"); player_id = read_int("player_id"); read_hturn("turn", &turn); /* Hack -- no ghosts */ /*r_info[z_info->r_max - 1].max_num = 0;*/ end_section_read("mangband_server_save"); /* Check for errors */ if (ferror(file_handle)) err = -1; /* Close the file */ my_fclose(file_handle); /* Result */ return (err); }
/* * Read the player inventory * * Note that the inventory changed in Angband 2.7.4. Two extra * pack slots were added and the equipment was rearranged. Note * that these two features combine when parsing old save-files, in * which items from the old "aux" slot are "carried", perhaps into * one of the two new "inventory" slots. * * Note that the inventory is "re-sorted" later by "dungeon()". */ static errr rd_inventory(player_type *p_ptr) { int slot = 0; object_type forge; start_section_read("inventory"); /* No weight */ p_ptr->total_weight = 0; /* No items */ p_ptr->inven_cnt = 0; p_ptr->equip_cnt = 0; /* Read until done */ while (1) { u16b n; /* Get the next item index */ n = read_int("inv_entry"); /* Nope, we reached the end */ if (n == 0xFFFF) break; /* Read the item */ rd_item(&forge); /* Hack -- verify item */ if (!forge.k_idx) return (53); /* Mega-Hack -- Handle artifacts that aren't yet "created" */ if (artifact_p(&forge)) { /* If this artifact isn't created, mark it as created */ /* Only if this isn't a "death" restore */ if (!a_info[forge.name1].cur_num && !p_ptr->death) a_info[forge.name1].cur_num = 1; } /* Wield equipment */ if (n >= INVEN_WIELD) { /* Structure copy */ p_ptr->inventory[n] = forge; /* Add the weight */ p_ptr->total_weight += (forge.number * forge.weight); /* One more item */ p_ptr->equip_cnt++; } /* Warning -- backpack is full */ else if (p_ptr->inven_cnt == INVEN_PACK) { /* Oops */ /*note("Too many items in the inventory!");*/ /* Fail */ return (54); } /* Carry inventory */ else { /* Get a slot */ n = slot++; /* Structure copy */ p_ptr->inventory[n] = forge; /* Add the weight */ p_ptr->total_weight += (forge.number * forge.weight); /* One more item */ p_ptr->inven_cnt++; } } end_section_read("inventory"); /* Success */ return (0); }
/** * 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; }