+ * When a monster is at a place where player will return,
+ * Get out of the my way!
+ */
+static void get_out_monster(void)
+{
+ int tries = 0;
+ int dis = 1;
+ int oy = py;
+ int ox = px;
+ int m_idx = cave[oy][ox].m_idx;
+
+ /* Nothing to do if no monster */
+ if (!m_idx) return;
+
+ /* Look until done */
+ while (TRUE)
+ {
+ monster_type *m_ptr;
+
+ /* Pick a (possibly illegal) location */
+ int ny = rand_spread(oy, dis);
+ int nx = rand_spread(ox, dis);
+
+ tries++;
+
+ /* Stop after 1000 tries */
+ if (tries > 10000) return;
+
+ /*
+ * Increase distance after doing enough tries
+ * compared to area of possible space
+ */
+ if (tries > 20 * dis * dis) dis++;
+
+ /* Ignore illegal locations */
+ if (!in_bounds(ny, nx)) continue;
+
+ /* Require "empty" floor space */
+ if (!cave_empty_bold(ny, nx)) continue;
+
+ /* Hack -- no teleport onto glyph of warding */
+ if (is_glyph_grid(&cave[ny][nx])) continue;
+ if (is_explosive_rune_grid(&cave[ny][nx])) continue;
+
+ /* ...nor onto the Pattern */
+ if (pattern_tile(ny, nx)) continue;
+
+ /*** It's a good place ***/
+
+ m_ptr = &m_list[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;
+
+ /* No need to do update_mon() */
+
+ /* Success */
+ return;
+ }
+}
+
+
+/*
+ * 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))
+
+
+/*
+ * Virtually teleport onto the stairs that is connecting between two
+ * floors.
+ *
+ * Teleport level spell and trap doors will always lead the player to
+ * the one of the floors connected by the one of the stairs in the
+ * current floor.
+ */
+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];
+ }
+}
+
+/*