/* * Builds the arena after it is entered -KMW- */ static void build_battle(void) { int yval, y_height, y_depth, xval, x_left, x_right; register int i, j; yval = SCREEN_HGT / 2; xval = SCREEN_WID / 2; y_height = yval - 10; y_depth = yval + 10; x_left = xval - 32; x_right = xval + 32; for (i = y_height; i <= y_height + 5; i++) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (i = y_depth; i >= y_depth - 3; i--) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_left; j <= x_left + 17; j++) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_right; j >= x_right - 17; j--) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } place_extra_perm_bold(y_height+6, x_left+18); cave[y_height+6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_depth-4, x_left+18); cave[y_depth-4][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_height+6, x_right-18); cave[y_height+6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_depth-4, x_right-18); cave[y_depth-4][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); for (i = y_height + 1; i <= y_height + 5; i++) for (j = x_left + 20 + 2 * (y_height + 5 - i); j <= x_right - 20 - 2 * (y_height + 5 - i); j++) { cave[i][j].feat = feat_permanent_glass_wall; } i = y_height + 1; j = xval; cave[i][j].feat = f_tag_to_index("BUILDING_3"); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); player_place(i, j); }
/* * 函数 void output_map(Game *game); * 参数:game 指向游戏数据结构体的指针 * 作用:输出游戏的地图 * 作者: */ void output_map(Game *game) { int i; char **map; map = init_print_map(game); for(i=0;i < game->player_num;i++) { player_place(game->players[i],map); } print(map); return; }
/* * Builds the arena after it is entered -KMW- */ static void build_arena(void) { int yval, y_height, y_depth, xval, x_left, x_right; register int i, j; yval = SCREEN_HGT / 2; xval = SCREEN_WID / 2; y_height = yval - 10; y_depth = yval + 10; x_left = xval - 32; x_right = xval + 32; for (i = y_height; i <= y_height + 5; i++) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); } for (i = y_depth; i >= y_depth - 5; i--) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); } for (j = x_left; j <= x_left + 17; j++) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); } for (j = x_right; j >= x_right - 17; j--) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); } place_extra_perm_bold(y_height+6, x_left+18); cave[y_height+6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); place_extra_perm_bold(y_depth-6, x_left+18); cave[y_depth-6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); place_extra_perm_bold(y_height+6, x_right-18); cave[y_height+6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); place_extra_perm_bold(y_depth-6, x_right-18); cave[y_depth-6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); i = y_height + 5; j = xval; cave[i][j].feat = f_tag_to_index("ARENA_GATE"); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK | CAVE_AWARE); player_place(i, j); }
/** * Place the player at a random starting location. * \param c current chunk * \param p the player */ void new_player_spot(struct chunk *c, struct player *p) { int y, x; /* Try to find a good place to put the player */ cave_find_in_range(c, &y, 0, c->height, &x, 0, c->width, square_isstart); /* Create stairs the player came down if allowed and necessary */ if (OPT(birth_no_stairs)) ; else if (p->upkeep->create_down_stair) square_set_feat(c, y, x, FEAT_MORE); else if (p->upkeep->create_up_stair) square_set_feat(c, y, x, FEAT_LESS); player_place(c, p, y, x); }
/** * Place the player at a random starting location. * \param c current chunk * \param p the player */ void new_player_spot(struct chunk *c, struct player *p) { int y, x; /* Try to find a good place to put the player */ if (OPT(p, birth_levels_persist) && square_in_bounds_fully(c, p->py, p->px) && square_isstairs(c, p->py, p->px)) { y = p->py; x = p->px; } else if (!find_start(c, &y, &x)) { quit("Failed to place player!"); } /* Create stairs the player came down if allowed and necessary */ if (!OPT(p, birth_connect_stairs)) ; else if (p->upkeep->create_down_stair) square_set_feat(c, y, x, FEAT_MORE); else if (p->upkeep->create_up_stair) square_set_feat(c, y, x, FEAT_LESS); player_place(c, p, 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 int rd_dungeon(void) { int i, y, x; s16b depth; s16b py, px; s16b ymax, xmax; byte count; byte tmp8u; u16b tmp16u; /* Only if the player's alive */ if (p_ptr->is_dead) return 0; /*** Basic info ***/ /* Header info */ rd_s16b(&depth); rd_u16b(&tmp16u); rd_s16b(&py); rd_s16b(&px); rd_s16b(&ymax); rd_s16b(&xmax); rd_u16b(&tmp16u); 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 ((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; } } } /* 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_info2[y][x] = tmp8u; /* Advance/Wrap */ if (++x >= DUNGEON_WID) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= DUNGEON_HGT) break; } } } /*** 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 "feat" */ cave_set_feat(y, x, tmp8u); /* Advance/Wrap */ if (++x >= DUNGEON_WID) { /* Wrap */ x = 0; /* Advance/Wrap */ if (++y >= DUNGEON_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); } /*** Success ***/ /* The dungeon is ready */ character_dungeon = TRUE; #if 0 /* Regenerate town in old versions */ if (p_ptr->depth == 0) character_dungeon = FALSE; #endif 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. * * 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); }
/** * Returns co-ordinates for the player. Player prefers to be near * walls, because large open spaces are dangerous. */ void new_player_spot(void) { int i = 0; int y, x; feature_type *f_ptr; /* * Check stored stair locations, then search at random. */ while (TRUE) { i++; /* Scan stored locations first. */ if (i < dun->stair_n) { /* Get location */ y = dun->stair[i].y; x = dun->stair[i].x; /* Require exactly three adjacent walls */ if (next_to_walls(y, x) != 3) continue; /* If character starts on stairs, ... */ if (!OPT(adult_no_stairs) || !p_ptr->depth) { /* Accept stairs going the right way or floors. */ if (p_ptr->create_stair) { /* Accept correct stairs */ if (cave_feat[y][x] == p_ptr->create_stair) break; /* Accept floors, build correct stairs. */ f_ptr = &f_info[cave_feat[y][x]]; if (cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR)) { cave_set_feat(y, x, p_ptr->create_stair); break; } } } /* If character doesn't start on stairs, ... */ else { /* Accept only "naked" floor grids */ f_ptr = &f_info[cave_feat[y][x]]; if (cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR)) break; } } /* Then, search at random */ else { /* Pick a random grid */ y = randint0(DUNGEON_HGT); x = randint0(DUNGEON_WID); /* Refuse to start on anti-teleport (vault) grids */ if (cave_has(cave_info[y][x], CAVE_ICKY)) continue; /* Must be a "naked" floor grid */ f_ptr = &f_info[cave_feat[y][x]]; if (!(cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR))) continue; /* Player prefers to be near walls. */ if (i < 300 && (next_to_walls(y, x) < 2)) continue; else if (i < 600 && (next_to_walls(y, x) < 1)) continue; /* Success */ break; } } /* Place the player */ player_place(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 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); }
/** * Generate the "consistent" town features, and place the player * * Hack -- play with the R.N.G. to always yield the same town * layout, including the size and shape of the buildings, the * locations of the doorways, and the location of the stairs. */ static void town_gen_hack(void) { int i, y, x, k, n, py = 1, px = 1; int qy = DUNGEON_HGT / 3; int qx = DUNGEON_WID / 3; int stage = p_ptr->stage; int last_stage = p_ptr->last_stage; int rooms[MAX_STORES_BIG + 1]; int per_row = (MAP(DUNGEON) || MAP(FANILLA) ? 5 : 4); bool place = FALSE; bool major = FALSE; /* Hack -- Use the "simple" RNG */ Rand_quick = TRUE; /* Hack -- Induce consistent town layout */ for (i = 0; i < 10; i++) if (stage == towns[i]) Rand_value = seed_town[i]; if (MAP(DUNGEON) || MAP(FANILLA)) Rand_value = seed_town[0]; /* Set major town flag if necessary */ if ((stage > GLADDEN_FIELDS_TOWN) || MAP(DUNGEON) || MAP(FANILLA)) major = TRUE; /* Hack - reduce width for minor towns */ if (!major) qx /= 2; /* Prepare an Array of "remaining stores", and count them */ if (major) for (n = 0; n < MAX_STORES_BIG; n++) rooms[n] = n; else { rooms[0] = 9; rooms[1] = 3; rooms[2] = 4; rooms[3] = 7; n = 4; } if (MAP(DUNGEON) || MAP(FANILLA)) rooms[n++] = 9; /* No stores for ironmen away from home */ if ((!MODE(IRONMAN)) || (p_ptr->stage == p_ptr->home)) { /* Place two rows of stores */ for (y = 0; y < 2; y++) { /* Place two, four or five stores per row */ for (x = 0; x < per_row; x++) { /* Pick a random unplaced store */ k = ((n <= 1) ? 0 : randint0(n)); /* Build that store at the proper location */ build_store(rooms[k], y, x, stage); /* Shift the stores down, remove one store */ rooms[k] = rooms[--n]; /* Cut short if a minor town */ if ((x > 0) && !major) break; } } /* Hack -- Build the 9th store. Taken from Zangband */ if (major && (MAP(COMPRESSED) || MAP(EXTENDED))) build_store(rooms[0], randint0(2), 4, stage); } if (MAP(DUNGEON) || MAP(FANILLA)) { /* Place the stairs */ while (TRUE) { feature_type *f_ptr; /* Pick a location at least "three" from the outer walls */ y = 1 + rand_range(3, DUNGEON_HGT / 3 - 4); x = 1 + rand_range(3, DUNGEON_WID / 3 - 4); /* Require a floor grid */ f_ptr = &f_info[cave_feat[y][x]]; if (tf_has(f_ptr->flags, TF_FLOOR)) break; } /* Clear previous contents, add down stairs */ cave_set_feat(y, x, FEAT_MORE); /* Place the player */ player_place(y, x); } else { /* Place the paths */ for (n = 2; n < 6; n++) { /* Pick a path direction for the player if not obvious */ if (((!last_stage) || (last_stage == 255)) && (stage_map[stage][n])) last_stage = stage_map[stage][n]; /* Where did we come from? */ if ((last_stage) && (last_stage == stage_map[stage][n])) place = TRUE; /* Pick a location at least "three" from the corners */ y = 1 + rand_range(3, qy - 4); x = 1 + rand_range(3, qx - 4); /* Shove it to the wall, place the path */ switch (n) { case NORTH: { y = 1; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_NORTH); break; } case EAST: { x = qx - 2; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_EAST); break; } case SOUTH: { y = qy - 2; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_SOUTH); break; } case WEST: { x = 1; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_WEST); } } if (place) { py = y; px = x; place = FALSE; } } /* Place the player */ player_place(py, px); } /* Hack -- use the "complex" RNG */ Rand_quick = FALSE; }
/* * Builds the arena after it is entered -KMW- */ static void build_battle(void) { int yval, y_height, y_depth, xval, x_left, x_right; register int i, j; yval = SCREEN_HGT / 2; xval = SCREEN_WID / 2; y_height = yval - 10; y_depth = yval + 10; x_left = xval - 32; x_right = xval + 32; /* Hack: Move the arena down 5 lines so that messages do not obstruct the battle. Couldn't this be read from a file just like vaults/rooms in v_info?*/ y_height += 5; y_depth += 5; for (i = 0; i < y_height; i++) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (i = y_height; i <= y_height + 5; i++) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (i = y_depth; i >= y_depth - 3; i--) for (j = x_left; j <= x_right; j++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_left; j <= x_left + 17; j++) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_right; j >= x_right - 17; j--) for (i = y_height; i <= y_depth; i++) { place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } place_extra_perm_bold(y_height+6, x_left+18); cave[y_height+6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_depth-4, x_left+18); cave[y_depth-4][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_height+6, x_right-18); cave[y_height+6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); place_extra_perm_bold(y_depth-4, x_right-18); cave[y_depth-4][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); for (i = y_height + 1; i <= y_height + 5; i++) for (j = x_left + 20 + 2 * (y_height + 5 - i); j <= x_right - 20 - 2 * (y_height + 5 - i); j++) { cave[i][j].feat = feat_permanent_glass_wall; } i = y_height + 1; j = xval; cave[i][j].feat = f_tag_to_index("BUILDING_3"); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); player_place(i, j); }
/* * Build the wilderness area outside of the town. */ void wilderness_gen(void) { int i, y, x; bool daytime; cave_type *c_ptr; /* Big town */ cur_hgt = MAX_HGT; cur_wid = MAX_WID; /* Assume illegal panel */ panel_row_min = cur_hgt; panel_col_min = cur_wid; /* Init the wilderness */ process_dungeon_file("w_info.txt", 0, 0, max_wild_y, max_wild_x); x = p_ptr->wilderness_x; y = p_ptr->wilderness_y; /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); /* North border */ generate_area(y - 1, x, TRUE, FALSE); for (i = 1; i < MAX_WID - 1; i++) { border.north[i] = cave[MAX_HGT - 2][i].feat; } /* South border */ generate_area(y + 1, x, TRUE, FALSE); for (i = 1; i < MAX_WID - 1; i++) { border.south[i] = cave[1][i].feat; } /* West border */ generate_area(y, x - 1, TRUE, FALSE); for (i = 1; i < MAX_HGT - 1; i++) { border.west[i] = cave[i][MAX_WID - 2].feat; } /* East border */ generate_area(y, x + 1, TRUE, FALSE); for (i = 1; i < MAX_HGT - 1; i++) { border.east[i] = cave[i][1].feat; } /* North west corner */ generate_area(y - 1, x - 1, FALSE, TRUE); border.north_west = cave[MAX_HGT - 2][MAX_WID - 2].feat; /* North east corner */ generate_area(y - 1, x + 1, FALSE, TRUE); border.north_east = cave[MAX_HGT - 2][1].feat; /* South west corner */ generate_area(y + 1, x - 1, FALSE, TRUE); border.south_west = cave[1][MAX_WID - 2].feat; /* South east corner */ generate_area(y + 1, x + 1, FALSE, TRUE); border.south_east = cave[1][1].feat; /* Leaving the dungeon by stairs */ /* (needed before the town is loaded) */ if (p_ptr->leaving_dungeon) { p_ptr->oldpy = 0; p_ptr->oldpx = 0; } /* Create terrain of the current area */ generate_area(y, x, FALSE, FALSE); /* Special boundary walls -- North */ for (i = 0; i < MAX_WID; i++) { cave[0][i].feat = FEAT_PERM_SOLID; cave[0][i].mimic = border.north[i]; } /* Special boundary walls -- South */ for (i = 0; i < MAX_WID; i++) { cave[MAX_HGT - 1][i].feat = FEAT_PERM_SOLID; cave[MAX_HGT - 1][i].mimic = border.south[i]; } /* Special boundary walls -- West */ for (i = 0; i < MAX_HGT; i++) { cave[i][0].feat = FEAT_PERM_SOLID; cave[i][0].mimic = border.west[i]; } /* Special boundary walls -- East */ for (i = 0; i < MAX_HGT; i++) { cave[i][MAX_WID - 1].feat = FEAT_PERM_SOLID; cave[i][MAX_WID - 1].mimic = border.east[i]; } /* North west corner */ cave[0][0].mimic = border.north_west; /* North east corner */ cave[0][MAX_WID - 1].mimic = border.north_east; /* South west corner */ cave[MAX_HGT - 1][0].mimic = border.south_west; /* South east corner */ cave[MAX_HGT - 1][MAX_WID - 1].mimic = border.south_east; /* Day time */ if ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2)) daytime = TRUE; else daytime = FALSE; /* Light up or darken the area */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { /* Get the cave grid */ c_ptr = &cave[y][x]; if (daytime) { /* Assume lit */ c_ptr->info |= (CAVE_GLOW); /* Hack -- Memorize lit grids if allowed */ if (view_perma_grids) c_ptr->info |= (CAVE_MARK); } else { /* Darken "boring" features */ if ((c_ptr->feat <= FEAT_INVIS) || ((c_ptr->feat >= FEAT_DEEP_WATER) && (c_ptr->feat <= FEAT_MOUNTAIN)) || (x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1)) { /* Forget the grid */ c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK); } } } } player_place(p_ptr->oldpy, p_ptr->oldpx); p_ptr->leaving_dungeon = FALSE; /* Make some residents */ for (i = 0; i < MIN_M_ALLOC_TN; i++) { /* Make a resident */ (void)alloc_monster(3, TRUE); } /* Set rewarded quests to finished */ for (i = 0; i < max_quests; i++) { if (quest[i].status == QUEST_STATUS_REWARDED) quest[i].status = QUEST_STATUS_FINISHED; } }