X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Ffloors.c;h=64fd13754c3576eb228f8c77dca37456416452d5;hb=e82139f72b6898b92d8716b7607d3f28655239e0;hp=940099f75046a316a60a70263d4206dedaabaa01;hpb=343952105da33aeec42d320827bb94d01e03d658;p=hengband%2Fhengband.git diff --git a/src/floors.c b/src/floors.c index 940099f75..64fd13754 100644 --- a/src/floors.c +++ b/src/floors.c @@ -1,35 +1,36 @@ -/* File: floors.c */ - -/* Purpose: management of the saved floor */ - -/* - * Copyright (c) 2002 Mogami - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. +/*! + * @file floors.c + * @brief Êݸ¤µ¤ì¤¿³¬¤Î´ÉÍý / management of the saved floor + * @date 2014/01/04 + * @author + * Copyright (c) 2002 Mogami \n + * This software may be copied and distributed for educational, research, and \n + * not for profit purposes provided that this copyright and statement are \n + * included in all such copies. \n + * 2014 Deskull rearranged comment for Doxygen. \n */ #include "angband.h" #include "grid.h" -static s16b new_floor_id; /* floor_id of the destination */ -static u32b change_floor_mode; /* Mode flags for changing floor */ -static u32b latest_visit_mark; /* Max number of visit_mark */ +static s16b new_floor_id; /*!<¼¡¤Î¥Õ¥í¥¢¤ÎID / floor_id of the destination */ +static u32b change_floor_mode; /*!<¥Õ¥í¥¢°Ü¹Ô½èÍý¤Ë´Ø¤¹¤ë¥Õ¥é¥° / Mode flags for changing floor */ +static u32b latest_visit_mark; /*!<¥Õ¥í¥¢¤òÅϤ俲ó¿ô¡©(³ÎǧÃæ) / Max number of visit_mark */ -/* - * Initialize saved_floors array. Make sure that old temporal files - * are not remaining as gurbages. +/*! + * @brief Êݸ¥Õ¥í¥¢ÇÛÎó¤ò½é´ü²½¤¹¤ë / Initialize saved_floors array. + * @param force ¥Æ¥ó¥Ý¥é¥ê¥Õ¥¡¥¤¥ë¤¬»Ä¤Ã¤Æ¤¤¤¿¾ì¹ç¤â·Ù¹ð¤Ê¤·¤Ç¶¯À©Åª¤Ëºï½ü¤¹¤ë¡£ + * @details Make sure that old temporal files are not remaining as gurbages. + * @return ¤Ê¤· */ -void init_saved_floors(void) +void init_saved_floors(bool force) { char floor_savefile[1024]; int i; int fd = -1; int mode = 0644; - bool force = FALSE; #ifdef SET_UID # ifdef SECURE @@ -116,11 +117,10 @@ void init_saved_floors(void) #endif } - -/* - * Kill temporal files - * Should be called just before the game quit - * and before new game discarding saved game. +/*! + * @brief Êݸ¥Õ¥í¥¢Íѥƥó¥Ý¥é¥ê¥Õ¥¡¥¤¥ë¤òºï½ü¤¹¤ë / Kill temporal files + * @details Should be called just before the game quit. + * @return ¤Ê¤· */ void clear_saved_floor_files(void) { @@ -163,9 +163,10 @@ void clear_saved_floor_files(void) #endif } - -/* - * Get a pointer for an item of the saved_floors array. +/*! + * @brief Êݸ¥Õ¥í¥¢ID¤«¤é»²¾È¥Ý¥¤¥ó¥¿¤òÆÀ¤ë / Get a pointer for an item of the saved_floors array. + * @param floor_id Êݸ¥Õ¥í¥¢ID + * @return ID¤ËÂбþ¤¹¤ëÊݸ¥Õ¥í¥¢¤Î¥Ý¥¤¥ó¥¿¡¢¤Ê¤¤¾ì¹ç¤ÏNULL¤òÊÖ¤¹¡£ */ saved_floor_type *get_sf_ptr(s16b floor_id) { @@ -186,13 +187,18 @@ saved_floor_type *get_sf_ptr(s16b floor_id) } -/* - * kill a saved floor and get an empty space +/*! + * @brief »²¾È¥Ý¥¤¥ó¥¿Àè¤ÎÊݸ¥Õ¥í¥¢¤òËõ¾Ã¤¹¤ë / kill a saved floor and get an empty space + * @param sf_ptr Êݸ¥Õ¥í¥¢¤Î»²¾È¥Ý¥¤¥ó¥¿ + * @return ¤Ê¤· */ static void kill_saved_floor(saved_floor_type *sf_ptr) { char floor_savefile[1024]; + /* Paranoia */ + if (!sf_ptr) return; + /* Already empty */ if (!sf_ptr->floor_id) return; @@ -223,9 +229,11 @@ static void kill_saved_floor(saved_floor_type *sf_ptr) } -/* - * Initialize new saved floor and get its floor id. If number of - * saved floors are already MAX_SAVED_FLOORS, kill the oldest one. +/*! + * @brief ¿·µ¬¤ËÍøÍѲÄǽ¤ÊÊݸ¥Õ¥í¥¢¤òÊÖ¤¹ / Initialize new saved floor and get its floor id. + * @return ÍøÍѲÄǽ¤ÊÊݸ¥Õ¥í¥¢ID + * @details + * If number of saved floors are already MAX_SAVED_FLOORS, kill the oldest one. */ s16b get_new_floor_id(void) { @@ -277,7 +285,8 @@ s16b get_new_floor_id(void) sf_ptr->lower_floor_id = 0; sf_ptr->visit_mark = latest_visit_mark++; - /* sf_ptr->dun_level is not yet decided */ + /* sf_ptr->dun_level may be changed later */ + sf_ptr->dun_level = dun_level; /* Increment number of floor_id */ @@ -290,17 +299,19 @@ s16b get_new_floor_id(void) } -/* - * Prepare mode flags of changing floor +/*! + * @brief ¥Õ¥í¥¢ÀÚ¤êÂؤ¨»þ¤Î½èÍý¥Õ¥é¥°¤òÄɲ乤ë / Prepare mode flags of changing floor + * @param mode Äɲä·¤¿¤¤½ê»ý¥Õ¥é¥° + * @return ¤Ê¤· */ void prepare_change_floor_mode(u32b mode) { change_floor_mode |= mode; } - -/* - * Builds the dead end +/*! + * @brief ³¬ÃÊ°ÜÆ°Àè¤Î¥Õ¥í¥¢¤¬À¸À®¤Ç¤­¤Ê¤¤»þ¤Ë´Êñ¤Ê¹Ô¤­»ß¤Þ¤ê¥Þ¥Ã¥×¤òºîÀ®¤¹¤ë / Builds the dead end + * @return ¤Ê¤· */ static void build_dead_end(void) { @@ -309,6 +320,9 @@ static void build_dead_end(void) /* Clear and empty the cave */ clear_cave(); + /* Fill the arrays of floors and walls in the good proportions */ + set_floor_and_wall(0); + /* Smallest area */ cur_hgt = SCREEN_HGT; cur_wid = SCREEN_WID; @@ -319,7 +333,7 @@ static void build_dead_end(void) for (x = 0; x < MAX_WID; x++) { /* Create "solid" perma-wall */ - cave[y][x].feat = FEAT_PERM_SOLID; + place_solid_perm_bold(y, x); } } @@ -329,67 +343,100 @@ static void build_dead_end(void) /* Give one square */ place_floor_bold(py, px); + + wipe_generate_cave_flags(); } -/* - * Preserve_pets + +#define MAX_PARTY_MON 21 /*!< ¥Õ¥í¥¢°ÜÆ°»þ¤ËÀè¤Î¥Õ¥í¥¢¤ËÏ¢¤ì¤Æ¹Ô¤±¤ë¥Ú¥Ã¥È¤ÎºÇÂç¿ô Maximum number of preservable pets */ +static monster_type party_mon[MAX_PARTY_MON]; /*!< ¥Õ¥í¥¢°ÜÆ°¤ËÊݸ¤¹¤ë¥Ú¥Ã¥È¥â¥ó¥¹¥¿¡¼¤ÎÇÛÎó */ + +/*! + * @brief ¥Õ¥í¥¢°ÜÆ°»þ¤Î¥Ú¥Ã¥ÈÊݸ½èÍý / Preserve_pets + * @return ¤Ê¤· */ static void preserve_pet(void) { int num, i; - for(num = 0; num < 21; num++) + for (num = 0; num < MAX_PARTY_MON; num++) { party_mon[num].r_idx = 0; } if (p_ptr->riding) { - COPY(&party_mon[0], &m_list[p_ptr->riding], monster_type); - - /* Delete from this floor */ - delete_monster_idx(p_ptr->riding); - } - - for(i = m_max - 1, num = 1; (i >= 1 && num < 21); i--) - { - monster_type *m_ptr = &m_list[i]; - - if (!m_ptr->r_idx) continue; - if (!is_pet(m_ptr)) continue; - if (i == p_ptr->riding) continue; + monster_type *m_ptr = &m_list[p_ptr->riding]; - if (reinit_wilderness) + /* Pet of other pet don't follow. */ + if (m_ptr->parent_m_idx) { - /* Don't lose sight of pets when getting a Quest */ + p_ptr->riding = 0; + p_ptr->pet_extra_flags &= ~(PF_RYOUTE); + p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE; } else { - int dis = distance(py, px, m_ptr->fy, m_ptr->fx); - - /* - * Pets with nickname will follow even from 3 blocks away - * when you or the pet can see the other. - */ - if (m_ptr->nickname && - (player_has_los_bold(m_ptr->fy, m_ptr->fx) || - los(m_ptr->fy, m_ptr->fx, py, px))) + /* Preserve the mount */ + (void)COPY(&party_mon[0], m_ptr, monster_type); + + /* Delete from this floor */ + delete_monster_idx(p_ptr->riding); + } + } + + /* + * If player is in wild mode, no pets are preserved + * except a monster whom player riding + */ + if (!p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) + { + for (i = m_max - 1, num = 1; (i >= 1 && num < MAX_PARTY_MON); i--) + { + monster_type *m_ptr = &m_list[i]; + + if (!m_ptr->r_idx) continue; + if (!is_pet(m_ptr)) continue; + if (i == p_ptr->riding) continue; + + if (reinit_wilderness) { - if (dis > 3) continue; + /* Don't lose sight of pets when getting a Quest */ } else { - if (dis > 1) continue; + int dis = distance(py, px, m_ptr->fy, m_ptr->fx); + + /* Confused (etc.) monsters don't follow. */ + if (MON_CONFUSED(m_ptr) || MON_STUNNED(m_ptr) || MON_CSLEEP(m_ptr)) continue; + + /* Pet of other pet don't follow. */ + if (m_ptr->parent_m_idx) continue; + + /* + * Pets with nickname will follow even from 3 blocks away + * when you or the pet can see the other. + */ + if (m_ptr->nickname && + ((player_has_los_bold(m_ptr->fy, m_ptr->fx) && projectable(py, px, m_ptr->fy, m_ptr->fx)) || + (los(m_ptr->fy, m_ptr->fx, py, px) && projectable(m_ptr->fy, m_ptr->fx, py, px)))) + { + if (dis > 3) continue; + } + else + { + if (dis > 1) continue; + } } - if (m_ptr->confused || m_ptr->stunned || m_ptr->csleep) continue; - } - COPY(&party_mon[num], &m_list[i], monster_type); - num++; + (void)COPY(&party_mon[num], &m_list[i], monster_type); - /* Delete from this floor */ - delete_monster_idx(i); + num++; + + /* Delete from this floor */ + delete_monster_idx(i); + } } if (record_named_pet) @@ -398,30 +445,81 @@ static void preserve_pet(void) { monster_type *m_ptr = &m_list[i]; char m_name[80]; - + if (!m_ptr->r_idx) continue; if (!is_pet(m_ptr)) continue; if (!m_ptr->nickname) continue; if (p_ptr->riding == i) continue; - - monster_desc(m_name, m_ptr, 0x88); - do_cmd_write_nikki(NIKKI_NAMED_PET, 4, m_name); + + monster_desc(m_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE); + do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_MOVED, m_name); + } + } + + + /* Pet of other pet may disappear. */ + for (i = m_max - 1; i >=1; i--) + { + monster_type *m_ptr = &m_list[i]; + + /* Are there its parent? */ + if (m_ptr->parent_m_idx && !m_list[m_ptr->parent_m_idx].r_idx) + { + /* Its parent have gone, it also goes away. */ + + if (is_seen(m_ptr)) + { + char m_name[80]; + + /* Acquire the monster name */ + monster_desc(m_name, m_ptr, 0); + +#ifdef JP + msg_format("%s¤Ï¾Ã¤¨µî¤Ã¤¿¡ª", m_name); +#else + msg_format("%^s disappears!", m_name); +#endif + } + + /* Delete the monster */ + delete_monster_idx(i); } } } -/* - * Place preserved pet monsters on new floor +/*! + * @brief ¥Õ¥í¥¢°ÜÆ°»þ¤Ë¥Ú¥Ã¥È¤òȼ¤Ã¤¿¾ì¹ç¤Î½àÈ÷½èÍý / Pre-calculate the racial counters of preserved pets + * @return ¤Ê¤· + * @details + * To prevent multiple generation of unique monster who is the minion of player */ -static void place_pet(void) +void precalc_cur_num_of_pet(void) { - int i, max_num; + monster_type *m_ptr; + int i; + int max_num = p_ptr->wild_mode ? 1 : MAX_PARTY_MON; - if (p_ptr->wild_mode) - max_num = 1; - else - max_num = 21; + for (i = 0; i < max_num; i++) + { + m_ptr = &party_mon[i]; + + /* Skip empty monsters */ + if (!m_ptr->r_idx) continue; + + /* Hack -- Increase the racial counter */ + real_r_ptr(m_ptr)->cur_num++; + } +} + +/*! + * @brief °ÜÆ°Àè¤Î¥Õ¥í¥¢¤Ëȼ¤Ã¤¿¥Ú¥Ã¥È¤òÇÛÃÖ¤¹¤ë / Place preserved pet monsters on new floor + * @return ¤Ê¤· + */ +static void place_pet(void) +{ + int i; + int max_num = p_ptr->wild_mode ? 1 : MAX_PARTY_MON; for (i = 0; i < max_num; i++) { @@ -429,7 +527,6 @@ static void place_pet(void) if (!(party_mon[i].r_idx)) continue; - if (i == 0) { m_idx = m_pop(); @@ -444,38 +541,35 @@ static void place_pet(void) { int j, d; - for(d = 1; d < 6; d++) + for (d = 1; d < 6; d++) { - for(j = 1000; j > 0; j--) + for (j = 1000; j > 0; j--) { scatter(&cy, &cx, py, px, d, 0); - if ((cave_floor_bold(cy, cx) || (cave[cy][cx].feat == FEAT_TREES)) && !cave[cy][cx].m_idx && !((cy == py) && (cx == px))) break; + if (monster_can_enter(cy, cx, &r_info[party_mon[i].r_idx], 0)) break; } if (j) break; } - if (d == 6 || p_ptr->inside_arena || p_ptr->inside_battle) - m_idx = 0; - else - m_idx = m_pop(); + m_idx = (d == 6) ? 0 : m_pop(); } - + if (m_idx) { monster_type *m_ptr = &m_list[m_idx]; monster_race *r_ptr; - + cave[cy][cx].m_idx = m_idx; m_ptr->r_idx = party_mon[i].r_idx; - r_ptr = real_r_ptr(m_ptr); /* Copy all member of the structure */ *m_ptr = party_mon[i]; + r_ptr = real_r_ptr(m_ptr); m_ptr->fy = cy; m_ptr->fx = cx; m_ptr->ml = TRUE; - m_ptr->csleep = 0; + m_ptr->mtimed[MTIMED_CSLEEP] = 0; /* Paranoia */ m_ptr->hold_o_idx = 0; @@ -485,49 +579,64 @@ static void place_pet(void) { /* Monster is still being nice */ m_ptr->mflag |= (MFLAG_NICE); - + /* Must repair monsters */ repair_monsters = TRUE; } - + /* Update the monster */ update_mon(m_idx, TRUE); lite_spot(cy, cx); - - r_ptr->cur_num++; - + + /* Pre-calculated in precalc_cur_num_of_pet() */ + /* r_ptr->cur_num++; */ + /* Hack -- Count the number of "reproducers" */ if (r_ptr->flags2 & RF2_MULTIPLY) num_repro++; - + /* Hack -- Notice new multi-hued monsters */ - if (r_ptr->flags1 & RF1_ATTR_MULTI) shimmer_monsters = TRUE; + { + monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx]; + if (ap_r_ptr->flags1 & (RF1_ATTR_MULTI | RF1_SHAPECHANGER)) + shimmer_monsters = TRUE; + } } else { + monster_type *m_ptr = &party_mon[i]; + monster_race *r_ptr = real_r_ptr(m_ptr); char m_name[80]; - - monster_desc(m_name, &party_mon[i], 0); + + monster_desc(m_name, m_ptr, 0); #ifdef JP msg_format("%s¤È¤Ï¤°¤ì¤Æ¤·¤Þ¤Ã¤¿¡£", m_name); #else msg_format("You have lost sight of %s.", m_name); #endif - if (record_named_pet && party_mon[i].nickname) + if (record_named_pet && m_ptr->nickname) { - monster_desc(m_name, &party_mon[i], 0x08); - do_cmd_write_nikki(NIKKI_NAMED_PET, 5, m_name); + monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE); + do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_LOST_SIGHT, m_name); } + + /* Pre-calculated in precalc_cur_num_of_pet(), but need to decrease */ + if (r_ptr->cur_num) r_ptr->cur_num--; } } + + /* For accuracy of precalc_cur_num_of_pet() */ + (void)C_WIPE(party_mon, MAX_PARTY_MON, monster_type); } -/* - * Hack -- Update location of unique monsters and artifacts - * - * The r_ptr->floor_id and a_ptr->floor_id are not updated correctly - * while new floor creation since dungeons may be re-created by - * auto-scum option. +/*! + * @brief ¥æ¥Ë¡¼¥¯¥â¥ó¥¹¥¿¡¼¤ä¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Î½êºß¥Õ¥í¥¢¤ò¹¹¿·¤¹¤ë / Hack -- Update location of unique monsters and artifacts + * @param cur_floor_id ¸½ºß¤Î¥Õ¥í¥¢ID + * @return ¤Ê¤· + * @details + * The r_ptr->floor_id and a_ptr->floor_id are not updated correctly\n + * while new floor creation since dungeons may be re-created by\n + * auto-scum option.\n */ static void update_unique_artifact(s16b cur_floor_id) { @@ -547,7 +656,7 @@ static void update_unique_artifact(s16b cur_floor_id) /* Memorize location of the unique monster */ if ((r_ptr->flags1 & RF1_UNIQUE) || - (r_ptr->flags7 & RF7_UNIQUE_7)) + (r_ptr->flags7 & RF7_NAZGUL)) { r_ptr->floor_id = cur_floor_id; } @@ -562,7 +671,7 @@ static void update_unique_artifact(s16b cur_floor_id) if (!o_ptr->k_idx) continue; /* Memorize location of the artifact */ - if (artifact_p(o_ptr)) + if (object_is_fixed_artifact(o_ptr)) { a_info[o_ptr->name1].floor_id = cur_floor_id; } @@ -570,9 +679,9 @@ static void update_unique_artifact(s16b cur_floor_id) } -/* - * When a monster is at a place where player will return, - * Get out of the my way! +/*! + * @brief ¥Õ¥í¥¢°ÜÆ°»þ¡¢¥×¥ì¥¤¥ä¡¼¤Î°ÜÆ°Àè¥â¥ó¥¹¥¿¡¼¤¬´û¤Ë¤¤¤¿¾ì¹ç¥é¥ó¥À¥à¤Ê¶áÎ٤˰ÜÆ°¤µ¤»¤ë / When a monster is at a place where player will return, + * @return ¤Ê¤· */ static void get_out_monster(void) { @@ -616,19 +725,18 @@ static void get_out_monster(void) if (is_explosive_rune_grid(&cave[ny][nx])) continue; /* ...nor onto the Pattern */ - if ((cave[ny][nx].feat >= FEAT_PATTERN_START) && - (cave[ny][nx].feat <= FEAT_PATTERN_XTRA2)) continue; + if (pattern_tile(ny, nx)) continue; /*** It's a good place ***/ m_ptr = &m_list[m_idx]; - /* Update the new location */ - cave[ny][nx].m_idx = m_idx; - /* Update the old location */ cave[oy][ox].m_idx = 0; + /* Update the new location */ + cave[ny][nx].m_idx = m_idx; + /* Move the monster */ m_ptr->fy = ny; m_ptr->fx = nx; @@ -640,14 +748,119 @@ static void get_out_monster(void) } } +/*! + * ¥Þ¥¹¹½Â¤ÂΤÎspecialÍ×ÁǤòÍøÍѤ¹¤ëÃÏ·Á¤«¤É¤¦¤«¤òȽÄꤹ¤ë¥Þ¥¯¥í / Is this feature has special meaning (except floor_id) with c_ptr->special? + */ +#define feat_uses_special(F) (have_flag(f_info[(F)].flags, FF_SPECIAL)) -/* - * Maintain quest monsters, mark next floor_id at stairs, save current - * floor, and prepare to enter next floor. + +/*! + * @brief ¿·¥Õ¥í¥¢¤Ë°ÜÆ°¸µ¥Õ¥í¥¢¤Ë·Ò¤¬¤ë³¬ÃʤòÇÛÃÖ¤¹¤ë / Virtually teleport onto the stairs that is connecting between two floors. + * @param sf_ptr °ÜÆ°¸µ¤ÎÊݸ¥Õ¥í¥¢¹½Â¤Âλ²¾È¥Ý¥¤¥ó¥¿ + * @return ¤Ê¤· + */ +static void locate_connected_stairs(saved_floor_type *sf_ptr) +{ + int x, y, sx = 0, sy = 0; + int x_table[20]; + int y_table[20]; + int num = 0; + int i; + + /* Search usable stairs */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + cave_type *c_ptr = &cave[y][x]; + feature_type *f_ptr = &f_info[c_ptr->feat]; + bool ok = FALSE; + + if (change_floor_mode & CFM_UP) + { + if (have_flag(f_ptr->flags, FF_LESS) && have_flag(f_ptr->flags, FF_STAIRS) && + !have_flag(f_ptr->flags, FF_SPECIAL)) + { + ok = TRUE; + + /* Found fixed stairs? */ + if (c_ptr->special && + c_ptr->special == sf_ptr->upper_floor_id) + { + sx = x; + sy = y; + } + } + } + + else if (change_floor_mode & CFM_DOWN) + { + if (have_flag(f_ptr->flags, FF_MORE) && have_flag(f_ptr->flags, FF_STAIRS) && + !have_flag(f_ptr->flags, FF_SPECIAL)) + { + ok = TRUE; + + /* Found fixed stairs */ + if (c_ptr->special && + c_ptr->special == sf_ptr->lower_floor_id) + { + sx = x; + sy = y; + } + } + } + + else + { + if (have_flag(f_ptr->flags, FF_BLDG)) + { + ok = TRUE; + } + } + + if (ok && (num < 20)) + { + x_table[num] = x; + y_table[num] = y; + num++; + } + } + } + + if (sx) + { + /* Already fixed */ + py = sy; + px = sx; + } + else if (!num) + { + /* No stairs found! -- No return */ + prepare_change_floor_mode(CFM_RAND_PLACE | CFM_NO_RETURN); + + /* Mega Hack -- It's not the stairs you enter. Disable it. */ + if (!feat_uses_special(cave[py][px].feat)) cave[py][px].special = 0; + } + else + { + /* Choose random one */ + i = randint0(num); + + /* Point stair location */ + py = y_table[i]; + px = x_table[i]; + } +} + +/*! + * @brief ¸½ºß¤Î¥Õ¥í¥¢¤òÎ¥¤ì¤ë¤Ëȼ¤Ã¤Æ¹Ô£ùÊݸ½èÍý + * / Maintain quest monsters, mark next floor_id at stairs, save current floor, and prepare to enter next floor. + * @return ¤Ê¤· */ void leave_floor(void) { cave_type *c_ptr = NULL; + feature_type *f_ptr; saved_floor_type *sf_ptr; int quest_r_idx = 0; int i; @@ -655,17 +868,24 @@ void leave_floor(void) /* Preserve pets and prepare to take these to next floor */ preserve_pet(); + /* Remove all mirrors without explosion */ + remove_all_mirrors(FALSE); + + if (p_ptr->special_defense & NINJA_S_STEALTH) set_superstealth(FALSE); + /* New floor is not yet prepared */ new_floor_id = 0; - - /* From somewhere of the surface to somewhere of the surface */ - if (!dungeon_type) + /* Temporary get a floor_id (for Arena) */ + if (!p_ptr->floor_id && + (change_floor_mode & CFM_SAVE_FLOORS) && + !(change_floor_mode & CFM_NO_RETURN)) { - /* No need to save current floor */ - return; + /* Get temporal floor_id */ + p_ptr->floor_id = get_new_floor_id(); } + /* Search the quest monster index */ for (i = 0; i < max_quests; i++) { @@ -697,7 +917,7 @@ void leave_floor(void) /* Ignore unique monsters */ if ((r_ptr->flags1 & RF1_UNIQUE) || - (r_ptr->flags7 & RF7_UNIQUE_7)) continue; + (r_ptr->flags7 & RF7_NAZGUL)) continue; /* Delete non-unique quest monsters */ delete_monster_idx(i); @@ -712,7 +932,7 @@ void leave_floor(void) if (!o_ptr->k_idx) continue; /* Delete old memorized location of the artifact */ - if (artifact_p(o_ptr)) + if (object_is_fixed_artifact(o_ptr)) { a_info[o_ptr->name1].floor_id = 0; } @@ -724,122 +944,55 @@ void leave_floor(void) /* Choose random stairs */ if ((change_floor_mode & CFM_RAND_CONNECT) && p_ptr->floor_id) { - int x, y, sx = 0, sy = 0; - int x_table[20]; - int y_table[20]; - int num = 0; - int i; - - /* Search usable stairs */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - cave_type *c_ptr = &cave[y][x]; - bool ok = FALSE; - - if (change_floor_mode & CFM_UP) - { - /* Found fixed stairs */ - if (c_ptr->special && - c_ptr->special == sf_ptr->upper_floor_id) - { - sx = x; - sy = y; - } - - if (c_ptr->feat == FEAT_LESS || - c_ptr->feat == FEAT_LESS_LESS) - ok = TRUE; - } - else if (change_floor_mode & CFM_DOWN) - { - /* Found fixed stairs */ - if (c_ptr->special && - c_ptr->special == sf_ptr->lower_floor_id) - { - sx = x; - sy = y; - } - - if (c_ptr->feat == FEAT_MORE || - c_ptr->feat == FEAT_MORE_MORE) - ok = TRUE; - } - - if (ok && num < 20) - { - x_table[num] = x; - y_table[num] = y; - num++; - } - } - } - - if (sx) - { - /* Already fixed */ - py = sy; - px = sx; - } - else if (!num) - { - /* No stairs found! -- No return */ - prepare_change_floor_mode(CFM_RAND_PLACE | CFM_NO_RETURN); - - /* Mega Hack -- It's not the stairs you enter. Disable it. */ - cave[py][px].special = 0; - } - else - { - /* Choose random one */ - i = randint0(num); - - /* Point stair location */ - py = y_table[i]; - px = x_table[i]; - } + locate_connected_stairs(sf_ptr); } /* Extract new dungeon level */ - if (!(change_floor_mode & CFM_CLEAR_ALL)) + if (change_floor_mode & CFM_SAVE_FLOORS) { - int move_num = 0; - /* Extract stair position */ c_ptr = &cave[py][px]; + f_ptr = &f_info[c_ptr->feat]; /* Get back to old saved floor? */ - if (dun_level && c_ptr->special && get_sf_ptr(c_ptr->special)) + if (c_ptr->special && !have_flag(f_ptr->flags, FF_SPECIAL) && get_sf_ptr(c_ptr->special)) { /* Saved floor is exist. Use it. */ new_floor_id = c_ptr->special; } - /* Extract level movement number */ - if (change_floor_mode & CFM_DOWN) move_num = 1; - else if (change_floor_mode & CFM_UP) move_num = -1; - /* Mark shaft up/down */ - if (c_ptr->feat == FEAT_LESS_LESS || - c_ptr->feat == FEAT_MORE_MORE) + if (have_flag(f_ptr->flags, FF_STAIRS) && have_flag(f_ptr->flags, FF_SHAFT)) { prepare_change_floor_mode(CFM_SHAFT); - move_num += SGN(move_num); } + } + + /* Climb up/down some sort of stairs */ + if (change_floor_mode & (CFM_DOWN | CFM_UP)) + { + int move_num = 0; + + /* Extract level movement number */ + if (change_floor_mode & CFM_DOWN) move_num = 1; + else if (change_floor_mode & CFM_UP) move_num = -1; + + /* Shafts are deeper than normal stairs */ + if (change_floor_mode & CFM_SHAFT) + move_num += SGN(move_num); /* Get out from or Enter the dungeon */ if (change_floor_mode & CFM_DOWN) { if (!dun_level) - move_num = d_info[c_ptr->special].mindepth; + move_num = d_info[dungeon_type].mindepth; } else if (change_floor_mode & CFM_UP) { if (dun_level + move_num < d_info[dungeon_type].mindepth) move_num = -dun_level; } - + dun_level += move_num; } @@ -856,10 +1009,11 @@ void leave_floor(void) dungeon_type = 0; /* Reach to the surface -- Clear all saved floors */ - prepare_change_floor_mode(CFM_CLEAR_ALL); + change_floor_mode &= ~CFM_SAVE_FLOORS; } - if (change_floor_mode & CFM_CLEAR_ALL) + /* Kill some old saved floors */ + if (!(change_floor_mode & CFM_SAVE_FLOORS)) { int i; @@ -891,13 +1045,10 @@ void leave_floor(void) new_floor_id = get_new_floor_id(); /* Connect from here */ - if (c_ptr) + if (c_ptr && !feat_uses_special(c_ptr->feat)) { c_ptr->special = new_floor_id; } - - /* Record new dungeon level */ - get_sf_ptr(new_floor_id)->dun_level = dun_level; } /* Fix connection -- level teleportation or trap door */ @@ -910,7 +1061,8 @@ void leave_floor(void) } /* If you can return, you need to save previous floor */ - if (!(change_floor_mode & (CFM_NO_RETURN | CFM_CLEAR_ALL))) + if ((change_floor_mode & CFM_SAVE_FLOORS) && + !(change_floor_mode & CFM_NO_RETURN)) { /* Get out of the my way! */ get_out_monster(); @@ -940,10 +1092,13 @@ void leave_floor(void) } -/* - * Enter new floor. If the floor is an old saved floor, it will be - * restored from the temporal file. If the floor is new one, new cave - * will be generated. +/*! + * @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) { @@ -965,13 +1120,14 @@ void change_floor(void) /* Mega-Hack -- not ambushed on the wildness? */ ambush_flag = FALSE; - /* On the surface */ - if (!dungeon_type) + /* 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 -- Now on the surface */ + /* Paranoia -- No new saved floor */ new_floor_id = 0; } @@ -1000,10 +1156,17 @@ void change_floor(void) if (change_floor_mode & CFM_NO_RETURN) { cave_type *c_ptr = &cave[py][px]; - - /* Reset to floor */ - place_floor_grid(c_ptr); - c_ptr->special = 0; + + 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; + } } } } @@ -1033,14 +1196,27 @@ void change_floor(void) } } + /* 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) { int i; - s32b absence_ticks = (turn - sf_ptr->last_visit) / TURNS_PER_TICK; + 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++) { @@ -1055,23 +1231,13 @@ void change_floor(void) /* Restore HP */ m_ptr->hp = m_ptr->maxhp = m_ptr->max_maxhp; - /* Remove fear */ - m_ptr->monfear = 0; - - /* Remove invulnerability */ - m_ptr->invulner = 0; - - /* Remove fast status */ - m_ptr->fast = 0; - - /* Remove slow status */ - m_ptr->slow = 0; - - /* Remove stun */ - m_ptr->stunned = 0; - - /* Remove confusion */ - m_ptr->confused = 0; + /* 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 */ @@ -1079,7 +1245,7 @@ void change_floor(void) /* Ignore non-unique */ if (!(r_ptr->flags1 & RF1_UNIQUE) && - !(r_ptr->flags7 & RF7_UNIQUE_7)) continue; + !(r_ptr->flags7 & RF7_NAZGUL)) continue; /* Appear at a different floor? */ if (r_ptr->floor_id != new_floor_id) @@ -1098,7 +1264,7 @@ void change_floor(void) if (!o_ptr->k_idx) continue; /* Ignore non-artifact */ - if (!artifact_p(o_ptr)) continue; + if (!object_is_fixed_artifact(o_ptr)) continue; /* Appear at a different floor? */ if (a_info[o_ptr->name1].floor_id != new_floor_id) @@ -1113,7 +1279,7 @@ void change_floor(void) } } - place_quest_monsters(); + (void)place_quest_monsters(); /* Place some random monsters */ alloc_times = absence_ticks / alloc_chance; @@ -1165,11 +1331,9 @@ void change_floor(void) /* Set correct dun_level value */ sf_ptr->dun_level = dun_level; - /* Creat connected stairs */ - if (!(change_floor_mode & (CFM_NO_RETURN | CFM_CLEAR_ALL)) && dun_level) + /* Create connected stairs */ + if (!(change_floor_mode & CFM_NO_RETURN)) { - bool ok = TRUE; - /* Extract stair position */ cave_type *c_ptr = &cave[py][px]; @@ -1178,34 +1342,20 @@ void change_floor(void) /* No stairs down from Quest */ if ((change_floor_mode & CFM_UP) && !quest_number(dun_level)) { - if (change_floor_mode & CFM_SHAFT) - c_ptr->feat = FEAT_MORE_MORE; - else - c_ptr->feat = FEAT_MORE; + 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) { - if (change_floor_mode & CFM_SHAFT) - c_ptr->feat = FEAT_LESS_LESS; - else - c_ptr->feat = FEAT_LESS; - } - else - { - /* Hum??? */ - ok = FALSE; + c_ptr->feat = (change_floor_mode & CFM_SHAFT) ? feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair; } - if (ok) - { - /* Paranoia -- Clear mimic */ - c_ptr->mimic = 0; + /* Paranoia -- Clear mimic */ + c_ptr->mimic = 0; - /* Connect to previous floor */ - c_ptr->special = p_ptr->floor_id; - } + /* Connect to previous floor */ + c_ptr->special = p_ptr->floor_id; } } @@ -1216,7 +1366,8 @@ void change_floor(void) } /* You see stairs blocked */ - else if (change_floor_mode & CFM_NO_RETURN) + else if ((change_floor_mode & CFM_NO_RETURN) && + (change_floor_mode & (CFM_DOWN | CFM_UP))) { if (!p_ptr->blind) { @@ -1250,6 +1401,9 @@ void change_floor(void) /* Place preserved pet monsters */ place_pet(); + /* Reset travel target place */ + forget_travel_flow(); + /* Hack -- maintain unique and artifacts */ update_unique_artifact(new_floor_id); @@ -1266,15 +1420,18 @@ void change_floor(void) /* 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; } - - -/* - * Create stairs at or move previously created stairs into the player - * location. +/*! + * @brief ¥×¥ì¥¤¥ä¡¼¤Î¼ê¤Ë¤è¤ëǽưŪ¤Ê³¬ÃÊÀ¸À®½èÍý / + * Create stairs at or move previously created stairs into the player location. + * @return ¤Ê¤· */ void stair_creation(void) { @@ -1294,7 +1451,7 @@ void stair_creation(void) /* No effect out of standard dungeon floor */ if (!dun_level || (!up && !down) || - (p_ptr->inside_quest && (p_ptr->inside_quest < MIN_RANDOM_QUEST)) || + (p_ptr->inside_quest && is_fixed_quest_idx(p_ptr->inside_quest)) || p_ptr->inside_arena || p_ptr->inside_battle) { /* arena or quest */ @@ -1324,6 +1481,14 @@ void stair_creation(void) /* 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) { @@ -1354,6 +1519,7 @@ void stair_creation(void) 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 */ @@ -1382,22 +1548,18 @@ void stair_creation(void) /* Create a staircase */ if (up) { - if (dest_sf_ptr->last_visit && dest_sf_ptr->dun_level <= dun_level - 2) - cave_set_feat(py, px, FEAT_LESS_LESS); - else - cave_set_feat(py, px, FEAT_LESS); + cave_set_feat(py, px, + (dest_sf_ptr->last_visit && (dest_sf_ptr->dun_level <= dun_level - 2)) ? + feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair); } else { - if (dest_sf_ptr->last_visit && dest_sf_ptr->dun_level >= dun_level + 2) - cave_set_feat(py, px, FEAT_MORE_MORE); - else - cave_set_feat(py, px, FEAT_MORE); + cave_set_feat(py, px, + (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[py][px].special = dest_floor_id; } - -