/* * Generate a new dungeon level * * Note that "dun_body" adds about 4000 bytes of memory to the stack. */ static bool cave_gen(void) { int i, j, k, y, x, y1, x1; int extraloot,ctx; int sizelootadjustment,totalattempts; int max_vault_ok = 3; int feat1, feat2; cave_type *c_ptr; bool destroyed = FALSE; bool empty_level = FALSE; bool cavern = FALSE; bool lairlevel = FALSE; /* Lair Level */ int lotsorooms = 0; int laketype = 0; int droom_min = DUN_ROOMS_MIN; int droom_max = DUN_ROOMS_MAX; int dmod = p_ptr->depth; int dmod2 = p_ptr->depth * 3; dun_data dun_body; if (dmod < 1) dmod = 1; if (one_in_(2)) lotsorooms = randint1(9)+1; /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); /* Global data */ dun = &dun_body; droom_min += dmod; droom_max += dmod2; if (droom_min > droom_max) droom_min = droom_max - 10; if (droom_max < droom_min) droom_max = droom_min + 10; if (droom_min < 1) { droom_min = 5; droom_max = 15; } if (lotsorooms) { droom_min *= lotsorooms; droom_max *= lotsorooms; } if (droom_min > 100) droom_min = 100; if (droom_max > 300) droom_max = 300; if (one_in_(11)) lairlevel = TRUE; extraloot = 0; ctx = 0; sizelootadjustment = 0; totalattempts = 0; sizelootadjustment = ((max_hgt - min_hgt) / 22) + ((max_wid - min_wid) / 66); if (sizelootadjustment < 1) sizelootadjustment = 1; if (max_hgt - min_hgt < 23) max_vault_ok--; if (max_wid - min_wid < 34) max_vault_ok--; /* Hack - no vaults in moria mode */ if (ironman_moria) max_vault_ok = 0; /* Randomize the dungeon creation values */ dun_rooms = rand_range(droom_min, droom_max); dun_tun_rnd = rand_range(DUN_TUN_RND_MIN, DUN_TUN_RND_MAX); dun_tun_chg = rand_range(DUN_TUN_CHG_MIN, DUN_TUN_CHG_MAX); dun_tun_con = rand_range(DUN_TUN_CON_MIN, DUN_TUN_CON_MAX); dun_tun_pen = rand_range(DUN_TUN_PEN_MIN, DUN_TUN_PEN_MAX); dun_tun_jct = rand_range(DUN_TUN_JCT_MIN, DUN_TUN_JCT_MAX); /* Empty arena levels */ if (ironman_empty_levels || (empty_levels && one_in_(EMPTY_LEVEL))) { empty_level = TRUE; if (cheat_room) msg_print("Arena level."); } /* Hack -- Start with basic granite */ for (y = min_hgt; y < max_hgt; y++) { for (x = min_wid; x < max_wid; x++) { if (empty_level) cave[y][x].feat = FEAT_FLOOR; else /* Create granite wall */ cave[y][x].feat = FEAT_WALL_EXTRA; } } /* Possible "destroyed" level */ if ((p_ptr->depth > 15) && one_in_(DUN_DEST) && (small_levels)) { destroyed = TRUE; /* extra rubble around the place looks cool */ build_lake(LAKE_DESTROY); } /* Make a lake some of the time */ if (one_in_(LAKE_LEVEL) && !empty_level && !destroyed && terrain_streams) { /* Lake of Water */ if (p_ptr->depth > 52) laketype = LAKE_WATER; /* Lake of Lava */ if (p_ptr->depth > 90) laketype = LAKE_LAVA; if (laketype != 0) { if (cheat_room) msg_print("Lake on the level."); build_lake(laketype); } } if (one_in_(DUN_CAV1/(p_ptr->depth + DUN_CAV2)) && !empty_level && (laketype == 0) && !destroyed && (p_ptr->depth >= MIN_CAVERN)) { cavern = TRUE; /* make a large fractal cave in the middle of the dungeon */ if (cheat_room) msg_print("Cavern on level."); build_cavern(); } /* Hack -- No destroyed "quest" levels */ if (quest_number(p_ptr->depth)) destroyed = FALSE; /* Actual maximum number of rooms on this level */ dun->row_rooms = (max_hgt - min_hgt) / BLOCK_HGT; dun->col_rooms = (max_wid - min_hgt) / BLOCK_WID; /* Initialize the room table */ for (y = 0; y < dun->row_rooms; y++) { for (x = 0; x < dun->col_rooms; x++) { dun->room_map[y][x] = FALSE; } } /* No "crowded" rooms yet */ dun->crowded = 0; /* No rooms yet */ dun->cent_n = 0; /* Build some rooms */ for (i = 0; i < dun_rooms; i++) { /* Pick a block for the room */ y = randint0(dun->row_rooms); x = randint0(dun->col_rooms); /* Align dungeon rooms */ if (dungeon_align) { /* Slide some rooms right */ if ((x % 3) == 0) x++; /* Slide some rooms left */ if ((x % 3) == 2) x--; } /* Attempt an "unusual" room */ if (ironman_rooms || (randint0(DUN_UNUSUAL) < p_ptr->depth)) { /* Roll for room type */ k = randint0(100); /* Attempt a very unusual room */ if ((ironman_rooms && (randint0(DUN_UNUSUAL) < p_ptr->depth * 2)) || (randint0(DUN_UNUSUAL) < p_ptr->depth)) { #ifdef FORCE_V_IDX if (room_build(y, x, 8)) continue; #else /* Type 8 -- Greater vault (10%) */ if (k < 10) { if (max_vault_ok > 1) { if (room_build(y, x, 8)) continue; } else { if (cheat_room) msg_format("Refusing a greater vault. %d", max_vault_ok); } } /* Type 7 -- Lesser vault (13%) */ if (k < 23) { if (max_vault_ok > 0) { if (room_build(y, x, 7)) continue; } else { if (cheat_room) msg_print("Refusing a lesser vault."); } } /* Type 5 -- Monster nest (8%) */ if ((k < 31) && room_build(y, x, 5)) continue; /* Type 6 -- Monster pit (5%) */ if ((k < 36) && room_build(y, x, 6)) continue; /* Type 10 -- Random vault (11%) */ if (k < 47) { if (max_vault_ok > 0) { if (room_build(y, x, 10)) continue; } else { if (cheat_room) msg_print("Refusing a random vault."); } } #endif } /* Type 4 -- Large room (15%) */ if ((k < 15) && room_build(y, x, 4)) continue; /* Type 14 -- Large room (10%) */ if ((k < 25) && room_build(y, x, 14)) continue; /* Type 13 -- Large Feature room (5%) */ if ((k < 30) && room_build(y, x, 13)) continue; /* Type 3 -- Cross room (20%) */ if ((k < 50) && room_build(y, x, 3)) continue; /* Type 2 -- Overlapping (25%) */ if ((k < 75) && room_build(y, x, 2)) continue; /* Type 11 -- Parallelagram (5%) */ if ((k < 80) && room_build(y, x, 15)) continue; /* Type 11 -- Circular (5%) */ if ((k < 85) && room_build(y, x, 11)) continue; /* Type 12 -- Crypt (15%) */ if ((k < 100) && room_build(y, x, 12)) continue; } /* The deeper you are, the more cavelike the rooms are */ k = randint1(100); /* No caves when a cavern exists: they look bad */ if ((k < p_ptr->depth) && (!cavern) && (!empty_level) && (laketype == 0)) { /* Type 9 -- Fractal cave */ if (room_build(y, x, 9)) continue; } else { /* Attempt a "trivial" room */ if (room_build(y, x, 1)) continue; } } /* Make a hole in the dungeon roof sometimes at level 1 */ if ((p_ptr->depth == 1) && terrain_streams) { while (one_in_(DUN_MOS_DEN)) { place_trees(rand_range(min_wid + 1, max_wid - 2), rand_range(min_hgt + 1, max_hgt - 2)); } } /* Destroy the level if necessary */ if (destroyed) destroy_level(); /* Hack -- Add some rivers */ if (one_in_(3) && (randint1(p_ptr->depth) > 5) && terrain_streams) { /* Choose water or lava */ if (randint0(MAX_DEPTH * 2) > p_ptr->depth) { feat1 = FEAT_DEEP_WATER; feat2 = FEAT_SHAL_WATER; } else { feat1 = FEAT_DEEP_LAVA; feat2 = FEAT_SHAL_LAVA; } /* Only add river if matches lake type or if have no lake at all */ if (((laketype == 1) && (feat1 == FEAT_DEEP_LAVA)) || ((laketype == 2) && (feat1 == FEAT_DEEP_WATER)) || (laketype == 0)) { add_river(feat1, feat2); } } /* Special boundary walls -- Top */ for (x = min_wid; x < max_wid; x++) { /* Clear previous contents, add "solid" perma-wall */ cave[min_hgt][x].feat = FEAT_PERM_SOLID; } /* Special boundary walls -- Bottom */ for (x = min_wid; x < max_wid; x++) { /* Clear previous contents, add "solid" perma-wall */ cave[max_hgt - 1][x].feat = FEAT_PERM_SOLID; } /* Special boundary walls -- Left */ for (y = min_hgt; y < max_hgt; y++) { /* Clear previous contents, add "solid" perma-wall */ cave[y][min_wid].feat = FEAT_PERM_SOLID; } /* Special boundary walls -- Right */ for (y = min_hgt; y < max_hgt; y++) { /* Clear previous contents, add "solid" perma-wall */ cave[y][max_wid - 1].feat = FEAT_PERM_SOLID; } /* Hack -- Scramble the room order */ for (i = 0; i < dun->cent_n; i++) { int pick1 = randint0(dun->cent_n); int pick2 = randint0(dun->cent_n); y1 = dun->cent[pick1].y; x1 = dun->cent[pick1].x; dun->cent[pick1].y = dun->cent[pick2].y; dun->cent[pick1].x = dun->cent[pick2].x; dun->cent[pick2].y = y1; dun->cent[pick2].x = x1; } /* Start with no tunnel doors */ dun->door_n = 0; /* Hack -- connect the first room to the last room */ y = dun->cent[dun->cent_n-1].y; x = dun->cent[dun->cent_n-1].x; /* Connect all the rooms together */ for (i = 0; i < dun->cent_n; i++) { /* Reset the arrays */ dun->tunn_n = 0; dun->wall_n = 0; /* Connect the room to the previous room */ #ifdef PILLAR_TUNNELS if ((randint1(20) > p_ptr->depth) && one_in_(4)) { /* make catacomb-like tunnel */ (void)build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 3, 30); } else if (randint1(p_ptr->depth) > 50) #else if (randint1(p_ptr->depth) > 50) #endif /* PILLAR_TUNNELS */ { /* make cave-like tunnel */ (void)build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 2, 2); } else { /* make normal tunnel */ build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x); } /* Turn the tunnel into corridor */ for (j = 0; j < dun->tunn_n; j++) { /* Access the grid */ y = dun->tunn[j].y; x = dun->tunn[j].x; /* Access the grid */ c_ptr = &cave[y][x]; /* Deleting a locked or jammed door is problematical */ delete_field_location(c_ptr); /* Clear previous contents (if not a lake), add a floor */ if ((c_ptr->feat < FEAT_DEEP_WATER) || (c_ptr->feat > FEAT_SHAL_LAVA)) { c_ptr->feat = FEAT_FLOOR; } } /* Apply the piercings that we found */ for (j = 0; j < dun->wall_n; j++) { /* Access the grid */ y = dun->wall[j].y; x = dun->wall[j].x; /* Access the grid */ c_ptr = &cave[y][x]; /* Deleting a locked or jammed door is problematical */ delete_field_location(c_ptr); /* Clear previous contents, add up floor */ c_ptr->feat = FEAT_FLOOR; /* Occasional doorway */ if (randint0(100) < dun_tun_pen) { /* Place a random door */ place_random_door(y, x); } } /* Remember the "previous" room */ y = dun->cent[i].y; x = dun->cent[i].x; } /* Place intersection doors */ for (i = 0; i < dun->door_n; i++) { /* Extract junction location */ y = dun->door[i].y; x = dun->door[i].x; /* Try placing doors */ try_door(y, x - 1); try_door(y, x + 1); try_door(y - 1, x); try_door(y + 1, x); } /* Hack -- Add some magma streamers */ for (i = 0; i < DUN_STR_MAG; i++) { build_streamer(FEAT_MAGMA, DUN_STR_MC); } /* Hack -- Add some quartz streamers */ for (i = 0; i < DUN_STR_QUA; i++) { build_streamer(FEAT_QUARTZ, DUN_STR_QC); } /* Place 3 or 4 down stairs near some walls */ if (!alloc_stairs(FEAT_MORE, rand_range(3, 4), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ if (!alloc_stairs(FEAT_LESS, rand_range(3, 4), 3)) return FALSE; /* Handle the quest monster placements */ for (i = 0; i < max_quests; i++) { if ((quest[i].status == QUEST_STATUS_TAKEN) && ((quest[i].type == QUEST_TYPE_KILL_LEVEL) || (quest[i].type == QUEST_TYPE_RANDOM)) && (quest[i].level == p_ptr->depth) && !(quest[i].flags & QUEST_FLAG_PRESET)) { monster_race *r_ptr = &r_info[quest[i].r_idx]; /* Hack -- "unique" monsters must be "unique" */ if ((r_ptr->flags1 & RF1_UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num)) { /* The unique is already dead */ quest[i].status = QUEST_STATUS_FINISHED; } else { bool group; /* Hard quests -> revive all monsters */ if (ironman_hard_quests) { quest[i].cur_num = 0; } for (j = 0; j < (quest[i].max_num - quest[i].cur_num); j++) { for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) { /* Find an empty grid */ while (TRUE) { y = rand_range(min_hgt + 1, max_hgt - 2); x = rand_range(min_wid + 1, max_wid - 2); /* Access the grid */ c_ptr = &cave[y][x]; if (!cave_naked_grid(c_ptr)) continue; if (distance(y, x, p_ptr->py, p_ptr->px) < 10) continue; else break; } if (r_ptr->flags1 & RF1_FRIENDS) group = FALSE; else group = TRUE; /* Try to place the monster */ if (place_monster_aux(y, x, quest[i].r_idx, FALSE, group, FALSE, FALSE)) { /* Success */ break; } else { /* Failure - Try again */ continue; } } } } } } /* Basic "amount" */ k = (p_ptr->depth / 3); if (k > 10) k = 10; if (k < 2) k = 2; /* Pick a base number of monsters */ i = MIN_M_ALLOC_LEVEL; if (!(lairlevel)) { /* To make small levels a bit more playable */ if (max_hgt < MAX_HGT || max_wid < MAX_WID) { int small_tester = i; i = (i * max_hgt) / MAX_HGT; i = (i * max_wid) / MAX_WID; i += 1; if (i > small_tester) i = small_tester; else if (cheat_hear) { msg_format("Reduced monsters base from %d to %d", small_tester, i); } } i += randint1(8); /* Put some monsters in the dungeon */ for (i = i + k; i > 0; i--) { (void)alloc_monster(0, TRUE); } } if (lairlevel) { int r_idx = get_mon_num(p_ptr->depth + randint1(12) + 3), attempts = (randint1(200)+100); monster_race *r_ptr = &r_info[r_idx]; attempts += ((10 + sizelootadjustment) * r_ptr->level); if (cheat_room) msg_print("Smile! Then Die!"); totalattempts = 0; while (attempts && (totalattempts <= 10000)) { /* attempts--;*/ ctx = 0; y = rand_range(min_hgt + 1, max_hgt - 2); x = rand_range(min_wid + 1, max_wid - 2); /* Access the grid */ c_ptr = &cave[y][x]; if (!cave_naked_grid(c_ptr)) ctx = 1; if (distance(y, x, p_ptr->py, p_ptr->px) < 10) ctx = 1; /* Try to place the monster */ if (ctx == 0) { if (place_monster_aux(y, x, r_idx, FALSE, (one_in_(10)) ? TRUE : FALSE, FALSE, FALSE)) { extraloot++; attempts--; } } totalattempts++; } } /* Place some traps in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k)); /* Put some rubble in corridors */ alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k)); /* Put some objects in rooms */ alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3)); if (lairlevel) { alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k*30)); /* Hack - Make loot desirable! */ /* AKA - Sucker in the PC */ dun_theme.treasure = qreward_theme[p_ptr->pclass].treasure; dun_theme.combat = qreward_theme[p_ptr->pclass].combat; dun_theme.magic = qreward_theme[p_ptr->pclass].magic; dun_theme.tools = qreward_theme[p_ptr->pclass].tools; /* Put loot! in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, extraloot); alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, extraloot); } /* Hack - Reset the object theme */ dun_theme.treasure = 20; dun_theme.combat = 20; dun_theme.magic = 20; dun_theme.tools = 20; /* Put some objects/gold in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3)); alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3)); /* Put some invisible walls in the dungeon for nightmare mode */ if (ironman_nightmare) { alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_INVIS, randnor(DUN_AMT_INVIS, 3)); } if (empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > p_ptr->depth))) { /* Lite the cave */ for (y = min_hgt; y < max_hgt; y++) { for (x = min_hgt; x < max_wid; x++) { cave[y][x].info |= (CAVE_GLOW); } } } /* Determine the character location */ if (!new_player_spot()) return FALSE; return TRUE; }
/*! * @brief フロアの切り替え処理 / Enter new floor. * @return なし * @details * If the floor is an old saved floor, it will be\n * restored from the temporal file. If the floor is new one, new cave\n * will be generated.\n */ void change_floor(void) { saved_floor_type *sf_ptr; bool loaded = FALSE; /* The dungeon is not ready */ character_dungeon = FALSE; /* No longer in the trap detecteded region */ p_ptr->dtrap = FALSE; /* Mega-Hack -- no panel yet */ panel_row_min = 0; panel_row_max = 0; panel_col_min = 0; panel_col_max = 0; /* Mega-Hack -- not ambushed on the wildness? */ ambush_flag = FALSE; /* No saved floors (On the surface etc.) */ if (!(change_floor_mode & CFM_SAVE_FLOORS) && !(change_floor_mode & CFM_FIRST_FLOOR)) { /* Create cave */ generate_cave(); /* Paranoia -- No new saved floor */ new_floor_id = 0; } /* In the dungeon */ else { /* No floor_id yet */ if (!new_floor_id) { /* Get new id */ new_floor_id = get_new_floor_id(); } /* Pointer for infomations of new floor */ sf_ptr = get_sf_ptr(new_floor_id); /* Try to restore old floor */ if (sf_ptr->last_visit) { /* Old saved floor is exist */ if (load_floor(sf_ptr, 0)) { loaded = TRUE; /* Forbid return stairs */ if (change_floor_mode & CFM_NO_RETURN) { cave_type *c_ptr = &cave[p_ptr->y][p_ptr->x]; if (!feat_uses_special(c_ptr->feat)) { if (change_floor_mode & (CFM_DOWN | CFM_UP)) { /* Reset to floor */ c_ptr->feat = floor_type[randint0(100)]; } c_ptr->special = 0; } } } } /* * Set lower/upper_floor_id of new floor when the new * floor is right-above/right-under the current floor. * * Stair creation/Teleport level/Trap door will take * you the same floor when you used it later again. */ if (p_ptr->floor_id) { saved_floor_type *cur_sf_ptr = get_sf_ptr(p_ptr->floor_id); if (change_floor_mode & CFM_UP) { /* New floor is right-above */ if (cur_sf_ptr->upper_floor_id == new_floor_id) sf_ptr->lower_floor_id = p_ptr->floor_id; } else if (change_floor_mode & CFM_DOWN) { /* New floor is right-under */ if (cur_sf_ptr->lower_floor_id == new_floor_id) sf_ptr->upper_floor_id = p_ptr->floor_id; } } /* Break connection to killed floor */ else { if (change_floor_mode & CFM_UP) sf_ptr->lower_floor_id = 0; else if (change_floor_mode & CFM_DOWN) sf_ptr->upper_floor_id = 0; } /* Maintain monsters and artifacts */ if (loaded) { IDX i; s32b tmp_last_visit = sf_ptr->last_visit; s32b absence_ticks; int alloc_chance = d_info[dungeon_type].max_m_alloc_chance; int alloc_times; while (tmp_last_visit > turn) tmp_last_visit -= TURNS_PER_TICK * TOWN_DAWN; absence_ticks = (turn - tmp_last_visit) / TURNS_PER_TICK; /* Maintain monsters */ for (i = 1; i < m_max; i++) { monster_race *r_ptr; monster_type *m_ptr = &m_list[i]; /* Skip dead monsters */ if (!m_ptr->r_idx) continue; if (!is_pet(m_ptr)) { /* Restore HP */ m_ptr->hp = m_ptr->maxhp = m_ptr->max_maxhp; /* Remove timed status (except MTIMED_CSLEEP) */ (void)set_monster_fast(i, 0); (void)set_monster_slow(i, 0); (void)set_monster_stunned(i, 0); (void)set_monster_confused(i, 0); (void)set_monster_monfear(i, 0); (void)set_monster_invulner(i, 0, FALSE); } /* Extract real monster race */ r_ptr = real_r_ptr(m_ptr); /* Ignore non-unique */ if (!(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_NAZGUL)) continue; /* Appear at a different floor? */ if (r_ptr->floor_id != new_floor_id) { /* Disapper from here */ delete_monster_idx(i); } } /* Maintain artifatcs */ for (i = 1; i < o_max; i++) { object_type *o_ptr = &o_list[i]; /* Skip dead objects */ if (!o_ptr->k_idx) continue; /* Ignore non-artifact */ if (!object_is_fixed_artifact(o_ptr)) continue; /* Appear at a different floor? */ if (a_info[o_ptr->name1].floor_id != new_floor_id) { /* Disappear from here */ delete_object_idx(i); } else { /* Cancel preserve */ a_info[o_ptr->name1].cur_num = 1; } } (void)place_quest_monsters(); /* Place some random monsters */ alloc_times = absence_ticks / alloc_chance; if (randint0(alloc_chance) < (absence_ticks % alloc_chance)) alloc_times++; for (i = 0; i < alloc_times; i++) { /* Make a (group of) new monster */ (void)alloc_monster(0, 0); } } /* New floor_id or failed to restore */ else /* if (!loaded) */ { if (sf_ptr->last_visit) { /* Temporal file is broken? */ #ifdef JP msg_print("階段は行き止まりだった。"); #else msg_print("The staircases come to a dead end..."); #endif /* Create simple dead end */ build_dead_end(); /* Break connection */ if (change_floor_mode & CFM_UP) { sf_ptr->upper_floor_id = 0; } else if (change_floor_mode & CFM_DOWN) { sf_ptr->lower_floor_id = 0; } } else { /* Newly create cave */ generate_cave(); } /* Record last visit turn */ sf_ptr->last_visit = turn; /* Set correct dun_level value */ sf_ptr->dun_level = dun_level; /* Create connected stairs */ if (!(change_floor_mode & CFM_NO_RETURN)) { /* Extract stair position */ cave_type *c_ptr = &cave[p_ptr->y][p_ptr->x]; /*** Create connected stairs ***/ /* No stairs down from Quest */ if ((change_floor_mode & CFM_UP) && !quest_number(dun_level)) { c_ptr->feat = (change_floor_mode & CFM_SHAFT) ? feat_state(feat_down_stair, FF_SHAFT) : feat_down_stair; } /* No stairs up when ironman_downward */ else if ((change_floor_mode & CFM_DOWN) && !ironman_downward) { c_ptr->feat = (change_floor_mode & CFM_SHAFT) ? feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair; } /* Paranoia -- Clear mimic */ c_ptr->mimic = 0; /* Connect to previous floor */ c_ptr->special = p_ptr->floor_id; } } /* Arrive at random grid */ if (change_floor_mode & (CFM_RAND_PLACE)) { (void)new_player_spot(); } /* You see stairs blocked */ else if ((change_floor_mode & CFM_NO_RETURN) && (change_floor_mode & (CFM_DOWN | CFM_UP))) { if (!p_ptr->blind) { #ifdef JP msg_print("突然階段が塞がれてしまった。"); #else msg_print("Suddenly the stairs is blocked!"); #endif } else { #ifdef JP msg_print("ゴトゴトと何か音がした。"); #else msg_print("You hear some noises."); #endif } } /* * Update visit mark * * The "turn" is not always different number because * the level teleport doesn't take any turn. Use * visit mark instead of last visit turn to find the * oldest saved floor. */ sf_ptr->visit_mark = latest_visit_mark++; } /* Place preserved pet monsters */ place_pet(); /* Reset travel target place */ forget_travel_flow(); /* Hack -- maintain unique and artifacts */ update_unique_artifact(new_floor_id); /* Now the player is in new floor */ p_ptr->floor_id = new_floor_id; /* The dungeon is ready */ character_dungeon = TRUE; /* Hack -- Munchkin characters always get whole map */ if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN) wiz_lite((bool)(p_ptr->pclass == CLASS_NINJA)); /* Remember when this level was "created" */ old_turn = turn; /* No dungeon feeling yet */ p_ptr->feeling_turn = old_turn; p_ptr->feeling = 0; /* Clear all flags */ change_floor_mode = 0L; select_floor_music(); }
/* * Generate a new dungeon level * * Note that "dun_body" adds about 4000 bytes of memory to the stack. */ static bool cave_gen(void) { int i, k, y, x; dun_data dun_body; /* Global data */ dun = &dun_body; dun->destroyed = FALSE; dun->empty_level = FALSE; dun->cavern = FALSE; dun->laketype = 0; /* Fill the arrays of floors and walls in the good proportions */ set_floor_and_wall(dungeon_type); /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); /* Randomize the dungeon creation values */ dun_tun_rnd = rand_range(DUN_TUN_RND_MIN, DUN_TUN_RND_MAX); dun_tun_chg = rand_range(DUN_TUN_CHG_MIN, DUN_TUN_CHG_MAX); dun_tun_con = rand_range(DUN_TUN_CON_MIN, DUN_TUN_CON_MAX); dun_tun_pen = rand_range(DUN_TUN_PEN_MIN, DUN_TUN_PEN_MAX); dun_tun_jct = rand_range(DUN_TUN_JCT_MIN, DUN_TUN_JCT_MAX); /* Actual maximum number of rooms on this level */ dun->row_rooms = cur_hgt / BLOCK_HGT; dun->col_rooms = cur_wid / BLOCK_WID; /* Initialize the room table */ for (y = 0; y < dun->row_rooms; y++) { for (x = 0; x < dun->col_rooms; x++) { dun->room_map[y][x] = FALSE; } } /* No rooms yet */ dun->cent_n = 0; /* Empty arena levels */ if (ironman_empty_levels || ((d_info[dungeon_type].flags1 & DF1_ARENA) && (empty_levels && one_in_(EMPTY_LEVEL)))) { dun->empty_level = TRUE; if (cheat_room) msg_print("Arena level."); } if (dun->empty_level) { /* Start with floors */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { place_floor_bold(y, x); } } /* Special boundary walls -- Top and bottom */ for (x = 0; x < cur_wid; x++) { place_extra_bold(0, x); place_extra_bold(cur_hgt - 1, x); } /* Special boundary walls -- Left and right */ for (y = 1; y < (cur_hgt - 1); y++) { place_extra_bold(y, 0); place_extra_bold(y, cur_wid - 1); } } else { /* Start with walls */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { place_extra_bold(y, x); } } } /* Generate various caverns and lakes */ gen_caverns_and_lakes(); /* Build maze */ if (d_info[dungeon_type].flags1 & DF1_MAZE) { build_maze_vault(cur_wid/2-1, cur_hgt/2-1, cur_wid-4, cur_hgt-4, FALSE); /* Place 3 or 4 down stairs near some walls */ if (!alloc_stairs(feat_down_stair, rand_range(4, 5), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ if (!alloc_stairs(feat_up_stair, 1, 2)) return FALSE; } /* Build some rooms */ else { int tunnel_fail_count = 0; /* * Build each type of room in turn until we cannot build any more. */ if (!generate_rooms()) return FALSE; /* Make a hole in the dungeon roof sometimes at level 1 But not in Angband. See Issue #3 */ if (dun_level == 1 && dungeon_type != DUNGEON_ANGBAND) { while (one_in_(DUN_MOS_DEN)) { place_trees(randint1(cur_wid - 2), randint1(cur_hgt - 2)); } } /* Destroy the level if necessary */ if (dun->destroyed) destroy_level(); /* Hack -- Add some rivers */ if (one_in_(7) && (randint1(dun_level) > 5)) { int feat1 = 0, feat2 = 0; /* Choose water or lava */ if ( randint1(MAX_DEPTH * 2) - 1 > dun_level && ( (d_info[dungeon_type].flags1 & DF1_WATER_RIVER) || (no_wilderness && one_in_(3)) ) ) { feat1 = feat_deep_water; feat2 = feat_shallow_water; } else if (d_info[dungeon_type].flags1 & DF1_LAVA_RIVER) { feat1 = feat_deep_lava; feat2 = feat_shallow_lava; } else feat1 = 0; if (feat1) { feature_type *f_ptr = &f_info[feat1]; /* Only add river if matches lake type or if have no lake at all */ if (((dun->laketype == LAKE_T_LAVA) && have_flag(f_ptr->flags, FF_LAVA)) || ((dun->laketype == LAKE_T_WATER) && have_flag(f_ptr->flags, FF_WATER)) || !dun->laketype) { add_river(feat1, feat2); } } } /* Hack -- Scramble the room order */ for (i = 0; i < dun->cent_n; i++) { int ty, tx; int pick = rand_range(0, i); ty = dun->cent[i].y; tx = dun->cent[i].x; dun->cent[i].y = dun->cent[pick].y; dun->cent[i].x = dun->cent[pick].x; dun->cent[pick].y = ty; dun->cent[pick].x = tx; } /* Start with no tunnel doors */ dun->door_n = 0; /* Hack -- connect the first room to the last room */ y = dun->cent[dun->cent_n-1].y; x = dun->cent[dun->cent_n-1].x; /* Connect all the rooms together */ for (i = 0; i < dun->cent_n; i++) { int j; /* Reset the arrays */ dun->tunn_n = 0; dun->wall_n = 0; /* Connect the room to the previous room */ if (randint1(dun_level) > d_info[dungeon_type].tunnel_percent) { /* make cave-like tunnel */ (void)build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 2, 2); } else { /* make normal tunnel */ if (!build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x)) tunnel_fail_count++; } if (tunnel_fail_count >= 2) return FALSE; /* Turn the tunnel into corridor */ for (j = 0; j < dun->tunn_n; j++) { cave_type *c_ptr; feature_type *f_ptr; /* Access the grid */ y = dun->tunn[j].y; x = dun->tunn[j].x; /* Access the grid */ c_ptr = &cave[y][x]; f_ptr = &f_info[c_ptr->feat]; /* Clear previous contents (if not a lake), add a floor */ if (!have_flag(f_ptr->flags, FF_MOVE) || (!have_flag(f_ptr->flags, FF_WATER) && !have_flag(f_ptr->flags, FF_LAVA))) { /* Clear mimic type */ c_ptr->mimic = 0; place_floor_grid(c_ptr); } } /* Apply the piercings that we found */ for (j = 0; j < dun->wall_n; j++) { cave_type *c_ptr; /* Access the grid */ y = dun->wall[j].y; x = dun->wall[j].x; /* Access the grid */ c_ptr = &cave[y][x]; /* Clear mimic type */ c_ptr->mimic = 0; /* Clear previous contents, add up floor */ place_floor_grid(c_ptr); /* Occasional doorway */ if ((randint0(100) < dun_tun_pen) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS)) { /* Place a random door */ place_random_door(y, x, TRUE); } } /* Remember the "previous" room */ y = dun->cent[i].y; x = dun->cent[i].x; } /* Place intersection doors */ for (i = 0; i < dun->door_n; i++) { /* Extract junction location */ y = dun->door[i].y; x = dun->door[i].x; /* Try placing doors */ try_door(y, x - 1); try_door(y, x + 1); try_door(y - 1, x); try_door(y + 1, x); } if (!alloc_stairs(feat_down_stair, rand_range(4, 5), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ if (!alloc_stairs(feat_up_stair, rand_range(1, 2), 3)) return FALSE; } if (!dun->laketype) { if (d_info[dungeon_type].stream2) { /* Hack -- Add some quartz streamers */ for (i = 0; i < DUN_STR_QUA; i++) { build_streamer(d_info[dungeon_type].stream2, DUN_STR_QC); } } if (d_info[dungeon_type].stream1) { /* Hack -- Add some magma streamers */ for (i = 0; i < DUN_STR_MAG; i++) { build_streamer(d_info[dungeon_type].stream1, DUN_STR_MC); } } } /* Special boundary walls -- Top and bottom */ for (x = 0; x < cur_wid; x++) { set_bound_perm_wall(&cave[0][x]); set_bound_perm_wall(&cave[cur_hgt - 1][x]); } /* Special boundary walls -- Left and right */ for (y = 1; y < (cur_hgt - 1); y++) { set_bound_perm_wall(&cave[y][0]); set_bound_perm_wall(&cave[y][cur_wid - 1]); } /* Determine the character location */ if (!new_player_spot()) return FALSE; /* Basic "amount" */ k = (dun_level / 3); if (k > 10) k = 10; if (k < 2) k = 2; /* Pick a base number of monsters */ i = d_info[dungeon_type].min_m_alloc_level; /* To make small levels a bit more playable */ if (cur_hgt < MAX_HGT || cur_wid < MAX_WID) { int small_tester = i; i = (i * cur_hgt) / MAX_HGT; i = (i * cur_wid) / MAX_WID; i += 1; if (i > small_tester) i = small_tester; else if (cheat_hear) { msg_format("Reduced monsters base from %d to %d", small_tester, i); } } if (dungeon_type != DUNGEON_ARENA) { i += randint1(8); /* Put some monsters in the dungeon */ for (i = (dun_level < 50 ? (i+k) : (i+k)*6/10); i > 0; i--) { (void)alloc_monster(0, PM_ALLOW_SLEEP); } } /* Place some traps in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k*3/2)); /* Put some rubble in corridors (except NO_CAVE dungeon (Castle)) */ if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE)) alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k)); if (dungeon_type != DUNGEON_ARENA) { /* Put some objects in rooms */ alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3)); /* Put some objects/gold in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3)); alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3)); /* Experimental: Guarantee certain objects. Give surprise goodies. */ if (one_in_(2)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_FOOD, 1); if (dun_level <= 15) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_LIGHT, 1); if (dun_level >= 10 && one_in_(2)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_RECALL, 1); if (dun_level >= 10 && one_in_(20)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_SKELETON, damroll(3, 5)); _mon_give_extra_drop(MFLAG2_DROP_BASIC, 1); _mon_give_extra_drop(MFLAG2_DROP_UTILITY, randint0(4)); if (dun_level > max_dlv[dungeon_type]) _mon_give_extra_drop(MFLAG2_DROP_PRIZE, 1); } /* Set back to default */ object_level = base_level; /* Put the Guardian */ if (!alloc_guardian(TRUE)) return FALSE; if (dun->empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) { /* Lite the cave */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave[y][x].info |= (CAVE_GLOW); } } } return TRUE; }
/** * Town logic flow for generation of new town * * We start with a fully wiped cave of normal floors. * * Note that town_gen_hack() plays games with the R.N.G. * * This function does NOT do anything about the owners of the stores, * nor the contents thereof. It only handles the physical layout. * * We place the player on the stairs at the same time we make them. * * Hack -- since the player always leaves the dungeon by the stairs, * he is always placed on the stairs, even if he left the dungeon via * word of recall or teleport level. */ static void town_gen(void) { int i, y, x; int residents; int stage = p_ptr->stage; int qy = 0; int qx = 0; int width = DUNGEON_WID / 3; bool dummy; /* Hack - smaller for minor towns */ if ((stage < KHAZAD_DUM_TOWN) && !MAP(DUNGEON) && !MAP(FANILLA)) width /= 2; /* Day time */ if (is_daylight) { /* Number of residents */ residents = MIN_M_ALLOC_TD; } /* Night time or cave */ else { /* Number of residents */ residents = MIN_M_ALLOC_TN; } /* Start with solid walls */ for (y = 0; y < DUNGEON_HGT; y++) { for (x = 0; x < DUNGEON_WID; x++) { /* Create "solid" perma-wall */ cave_set_feat(y, x, FEAT_PERM_SOLID); } } /* Boundary walls (see town_illuminate() */ for (x = qx; x < qx + width; x++) { cave_set_feat(qy, x, FEAT_PERM_INNER); cave_set_feat(qy + (DUNGEON_HGT / 3) - 1, x, FEAT_PERM_INNER); } /* Boundary walls (see town_illuminate() */ for (y = qy; y < qy + (DUNGEON_HGT / 3); y++) { cave_set_feat(y, qx, FEAT_PERM_INNER); cave_set_feat(y, qx + width - 1, FEAT_PERM_INNER); } /* Then place some floors */ for (y = qy + 1; y < qy + (DUNGEON_HGT / 3) - 1; y++) { for (x = qx + 1; x < qx + width - 1; x++) { /* Create empty floor */ cave_set_feat(y, x, FEAT_FLOOR); } } /* Build stuff */ town_gen_hack(); /* Remove restrictions */ (void) mon_restrict('\0', 0, &dummy, FALSE); /* Make some residents */ for (i = 0; i < residents; i++) { /* Make a resident */ (void) alloc_monster(3, TRUE, FALSE); } }
/* * 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; } }