/* * Set boundary mimic and add "solid" perma-wall */ static void set_bound_perm_wall(cave_type *c_ptr) { if (bound_walls_perm) { /* Clear boundary mimic */ c_ptr->mimic = 0; } else { feature_type *f_ptr = &f_info[c_ptr->feat]; /* Hack -- Decline boundary walls with known treasure */ if ((have_flag(f_ptr->flags, FF_HAS_GOLD) || have_flag(f_ptr->flags, FF_HAS_ITEM)) && !have_flag(f_ptr->flags, FF_SECRET)) c_ptr->feat = feat_state(c_ptr->feat, FF_ENSECRET); /* Set boundary mimic */ c_ptr->mimic = c_ptr->feat; } /* Add "solid" perma-wall */ place_solid_perm_grid(c_ptr); }
/*! * @brief プレイヤーの手による能動的な階段生成処理 / * Create stairs at or move previously created stairs into the player location. * @return なし */ void stair_creation(void) { saved_floor_type *sf_ptr; saved_floor_type *dest_sf_ptr; bool up = TRUE; bool down = TRUE; s16b dest_floor_id = 0; /* Forbid up staircases on Ironman mode */ if (ironman_downward) up = FALSE; /* Forbid down staircases on quest level */ if (quest_number(dun_level) || (dun_level >= d_info[dungeon_type].maxdepth)) down = FALSE; /* No effect out of standard dungeon floor */ if (!dun_level || (!up && !down) || (p_ptr->inside_quest && is_fixed_quest_idx(p_ptr->inside_quest)) || p_ptr->inside_arena || p_ptr->inside_battle) { /* arena or quest */ #ifdef JP msg_print("効果がありません!"); #else msg_print("There is no effect!"); #endif return; } /* Artifacts resists */ if (!cave_valid_bold(p_ptr->y, p_ptr->x)) { #ifdef JP msg_print("床上のアイテムが呪文を跳ね返した。"); #else msg_print("The object resists the spell."); #endif return; } /* Destroy all objects in the grid */ delete_object(p_ptr->y, p_ptr->x); /* Extract current floor data */ sf_ptr = get_sf_ptr(p_ptr->floor_id); /* Paranoia */ if (!sf_ptr) { /* No floor id? -- Create now! */ p_ptr->floor_id = get_new_floor_id(); sf_ptr = get_sf_ptr(p_ptr->floor_id); } /* Choose randomly */ if (up && down) { if (randint0(100) < 50) up = FALSE; else down = FALSE; } /* Destination is already fixed */ if (up) { if (sf_ptr->upper_floor_id) dest_floor_id = sf_ptr->upper_floor_id; } else { if (sf_ptr->lower_floor_id) dest_floor_id = sf_ptr->lower_floor_id; } /* Search old stairs leading to the destination */ if (dest_floor_id) { int x, y; for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave_type *c_ptr = &cave[y][x]; if (!c_ptr->special) continue; if (feat_uses_special(c_ptr->feat)) continue; if (c_ptr->special != dest_floor_id) continue; /* Remove old stairs */ c_ptr->special = 0; cave_set_feat(y, x, floor_type[randint0(100)]); } } } /* No old destination -- Get new one now */ else { dest_floor_id = get_new_floor_id(); /* Fix it */ if (up) sf_ptr->upper_floor_id = dest_floor_id; else sf_ptr->lower_floor_id = dest_floor_id; } /* Extract destination floor data */ dest_sf_ptr = get_sf_ptr(dest_floor_id); /* Create a staircase */ if (up) { cave_set_feat(p_ptr->y, p_ptr->x, (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level <= dun_level - 2)) ? feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair); } else { cave_set_feat(p_ptr->y, p_ptr->x, (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level >= dun_level + 2)) ? feat_state(feat_down_stair, FF_SHAFT) : feat_down_stair); } /* Connect this stairs to the destination */ cave[p_ptr->y][p_ptr->x].special = dest_floor_id; }
/*! * @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(); }
/* * Places some staircases near walls */ static bool alloc_stairs(int feat, int num, int walls) { int i; int shaft_num = 0; feature_type *f_ptr = &f_info[feat]; if (have_flag(f_ptr->flags, FF_LESS)) { /* No up stairs in town or in ironman mode */ if (ironman_downward || !dun_level) return TRUE; /* No way out!! if ( dun_level == d_info[dungeon_type].mindepth && (dungeon_flags[dungeon_type] & DUNGEON_NO_ENTRANCE) ) { return TRUE; } if ( dun_level == d_info[dungeon_type].mindepth + 1 && (dungeon_flags[dungeon_type] & DUNGEON_NO_ENTRANCE) ) { shaft_num = 0; } else */if (dun_level > d_info[dungeon_type].mindepth) shaft_num = (randint1(num+1))/2; } else if (have_flag(f_ptr->flags, FF_MORE)) { /* player must complete the quest to gain the down staircase */ if (!quests_allow_downstairs()) return TRUE; /* No downstairs on random wilderness entrances */ if (d_info[dungeon_type].flags1 & DF1_RANDOM) return TRUE; /* No downstairs at the bottom */ if (dun_level >= d_info[dungeon_type].maxdepth) return TRUE; if ( dun_level < d_info[dungeon_type].maxdepth - 1 /* Note: If we exclude downshafts, then the astute player can be certain * that normal stairs do *not* lead to a quest level. Instead, we'll change * the behavior of FF_SHAFT in do_cmd_go_down. */ /*&& quests_allow_downshaft()*/) { shaft_num = (randint1(num)+1)/2; if (quickband) shaft_num *= 2; } } /* Paranoia */ else return FALSE; /* Place "num" stairs */ for (i = 0; i < num; i++) { while (TRUE) { int y = 0, x = 0; cave_type *c_ptr; int candidates = 0; int pick; for (y = 1; y < cur_hgt - 1; y++) { for (x = 1; x < cur_wid - 1; x++) { if (alloc_stairs_aux(y, x, walls)) { /* A valid space found */ candidates++; } } } /* No valid place! */ if (!candidates) { /* There are exactly no place! */ if (walls <= 0) return FALSE; /* Decrease walls limit, and try again */ walls--; continue; } /* Choose a random one */ pick = randint1(candidates); for (y = 1; y < cur_hgt - 1; y++) { for (x = 1; x < cur_wid - 1; x++) { if (alloc_stairs_aux(y, x, walls)) { pick--; /* Is this a picked one? */ if (!pick) break; } } if (!pick) break; } /* Access the grid */ c_ptr = &cave[y][x]; /* Clear possible garbage of hidden trap */ c_ptr->mimic = 0; /* Clear previous contents, add stairs */ c_ptr->feat = (i < shaft_num) ? feat_state(feat, FF_SHAFT) : feat; /* No longer "FLOOR" */ c_ptr->info &= ~(CAVE_FLOOR); /* Success */ break; } } return TRUE; }
/* * Places some staircases near walls */ static bool alloc_stairs(int feat, int num, int walls) { int i; int shaft_num = 0; feature_type *f_ptr = &f_info[feat]; if (have_flag(f_ptr->flags, FF_LESS)) { /* No up stairs in town or in ironman mode */ if (ironman_downward || !dun_level) return TRUE; if (dun_level > d_info[dungeon_type].mindepth) shaft_num = (randint1(num+1))/2; } else if (have_flag(f_ptr->flags, FF_MORE)) { int q_idx = quest_number(dun_level); /* No downstairs on quest levels */ if (dun_level > 1 && q_idx) { monster_race *r_ptr = &r_info[quest[q_idx].r_idx]; /* The quest monster(s) is still alive? */ if (!(r_ptr->flags1 & RF1_UNIQUE) || 0 < r_ptr->max_num) return TRUE; } /* No downstairs at the bottom */ if (dun_level >= d_info[dungeon_type].maxdepth) return TRUE; if ((dun_level < d_info[dungeon_type].maxdepth-1) && !quest_number(dun_level+1)) shaft_num = (randint1(num)+1)/2; } /* Paranoia */ else return FALSE; /* Place "num" stairs */ for (i = 0; i < num; i++) { while (TRUE) { int y = 0, x = 0; cave_type *c_ptr; int candidates = 0; int pick; for (y = 1; y < cur_hgt - 1; y++) { for (x = 1; x < cur_wid - 1; x++) { if (alloc_stairs_aux(y, x, walls)) { /* A valid space found */ candidates++; } } } /* No valid place! */ if (!candidates) { /* There are exactly no place! */ if (walls <= 0) return FALSE; /* Decrease walls limit, and try again */ walls--; continue; } /* Choose a random one */ pick = randint1(candidates); for (y = 1; y < cur_hgt - 1; y++) { for (x = 1; x < cur_wid - 1; x++) { if (alloc_stairs_aux(y, x, walls)) { pick--; /* Is this a picked one? */ if (!pick) break; } } if (!pick) break; } /* Access the grid */ c_ptr = &cave[y][x]; /* Clear possible garbage of hidden trap */ c_ptr->mimic = 0; /* Clear previous contents, add stairs */ c_ptr->feat = (i < shaft_num) ? feat_state(feat, FF_SHAFT) : feat; /* No longer "FLOOR" */ c_ptr->info &= ~(CAVE_FLOOR); /* Success */ break; } } return TRUE; }