/*Place the effect in a stack of effects.*/ static void place_effect_idx(int x_idx, int y, int x) { /* Get this effect */ effect_type *x_ptr = &x_list[x_idx]; /* * Handle next_x_idx. Traps (and glyphs) always have first priority. */ if (cave_any_trap_bold(y, x)) { x_ptr->next_x_idx = x_list[cave_x_idx[y][x]].next_x_idx; x_list[cave_x_idx[y][x]].next_x_idx = x_idx; } else { x_ptr->next_x_idx = cave_x_idx[y][x]; cave_x_idx[y][x] = x_idx; } /* Update some CAVE_* flags */ update_los_proj_move(y, x); /* Redraw grid if necessary */ if (character_dungeon && !(x_ptr->x_flags & (EF1_HIDDEN))) { light_spot(y, x); } }
/* * 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); }