Term_xtra(TERM_XTRA_DELAY, delay_factor);
}
#endif
+
+
+#ifdef TRAVEL
+/*
+ * Hack: travel command
+ */
+#define TRAVEL_UNABLE 9999
+
+static int flow_head = 0;
+static int flow_tail = 0;
+static POSITION temp2_x[MAX_SHORT];
+static POSITION temp2_y[MAX_SHORT];
+
+/*!
+ * @brief トラベル処理の記憶配列を初期化する Hack: forget the "flow" information
+ * @return なし
+ */
+void forget_travel_flow(void)
+{
+ POSITION x, y;
+ /* Check the entire dungeon / Forget the old data */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+
+ travel.cost[y][x] = MAX_SHORT;
+ }
+ }
+ travel.y = travel.x = 0;
+}
+
+/*!
+ * @brief トラベル処理中に地形に応じた移動コスト基準を返す
+ * @param y 該当地点のY座標
+ * @param x 該当地点のX座標
+ * @return コスト値
+ */
+static int travel_flow_cost(POSITION y, POSITION x)
+{
+ feature_type *f_ptr = &f_info[grid_array[y][x].feat];
+ int cost = 1;
+
+ /* Avoid obstacles (ex. trees) */
+ if (have_flag(f_ptr->flags, FF_AVOID_RUN)) cost += 1;
+
+ /* Water */
+ if (have_flag(f_ptr->flags, FF_WATER))
+ {
+ if (have_flag(f_ptr->flags, FF_DEEP) && !p_ptr->levitation) cost += 5;
+ }
+
+ /* Lava */
+ if (have_flag(f_ptr->flags, FF_LAVA))
+ {
+ int lava = 2;
+ if (!p_ptr->resist_fire) lava *= 2;
+ if (!p_ptr->levitation) lava *= 2;
+ if (have_flag(f_ptr->flags, FF_DEEP)) lava *= 2;
+
+ cost += lava;
+ }
+
+ /* Detected traps and doors */
+ if (grid_array[y][x].info & (CAVE_MARK))
+ {
+ if (have_flag(f_ptr->flags, FF_DOOR)) cost += 1;
+ if (have_flag(f_ptr->flags, FF_TRAP)) cost += 10;
+ }
+
+ return (cost);
+}
+
+/*!
+ * @brief トラベル処理の到達地点までの行程を得る処理のサブルーチン
+ * @param y 目標地点のY座標
+ * @param x 目標地点のX座標
+ * @param n 現在のコスト
+ * @param wall プレイヤーが壁の中にいるならばTRUE
+ * @return なし
+ */
+static void travel_flow_aux(POSITION y, POSITION x, int n, bool wall)
+{
+ grid_type *g_ptr = &grid_array[y][x];
+ feature_type *f_ptr = &f_info[g_ptr->feat];
+ int old_head = flow_head;
+ int add_cost = 1;
+ int base_cost = (n % TRAVEL_UNABLE);
+ int from_wall = (n / TRAVEL_UNABLE);
+ int cost;
+
+ /* Ignore out of bounds */
+ if (!in_bounds(y, x)) return;
+
+ /* Ignore unknown grid except in wilderness */
+ if (dun_level > 0 && !(g_ptr->info & CAVE_KNOWN)) return;
+
+ /* Ignore "walls" and "rubble" (include "secret doors") */
+ if (have_flag(f_ptr->flags, FF_WALL) ||
+ have_flag(f_ptr->flags, FF_CAN_DIG) ||
+ (have_flag(f_ptr->flags, FF_DOOR) && grid_array[y][x].mimic) ||
+ (!have_flag(f_ptr->flags, FF_MOVE) && have_flag(f_ptr->flags, FF_CAN_FLY) && !p_ptr->levitation))
+ {
+ if (!wall || !from_wall) return;
+ add_cost += TRAVEL_UNABLE;
+ }
+ else
+ {
+ add_cost = travel_flow_cost(y, x);
+ }
+
+ cost = base_cost + add_cost;
+
+ /* Ignore lower cost entries */
+ if (travel.cost[y][x] <= cost) return;
+
+ /* Save the flow cost */
+ travel.cost[y][x] = cost;
+
+ /* Enqueue that entry */
+ temp2_y[flow_head] = y;
+ temp2_x[flow_head] = x;
+
+ /* Advance the queue */
+ if (++flow_head == MAX_SHORT) flow_head = 0;
+
+ /* Hack -- notice overflow by forgetting new entry */
+ if (flow_head == flow_tail) flow_head = old_head;
+
+ return;
+}
+
+/*!
+ * @brief トラベル処理の到達地点までの行程を得る処理のメインルーチン
+ * @param ty 目標地点のY座標
+ * @param tx 目標地点のX座標
+ * @return なし
+ */
+static void travel_flow(POSITION ty, POSITION tx)
+{
+ POSITION x, y;
+ DIRECTION d;
+ bool wall = FALSE;
+ feature_type *f_ptr = &f_info[grid_array[p_ptr->y][p_ptr->x].feat];
+
+ /* Reset the "queue" */
+ flow_head = flow_tail = 0;
+
+ /* is player in the wall? */
+ if (!have_flag(f_ptr->flags, FF_MOVE)) wall = TRUE;
+
+ /* Start at the target grid */
+ travel_flow_aux(ty, tx, 0, wall);
+
+ /* Now process the queue */
+ while (flow_head != flow_tail)
+ {
+ /* Extract the next entry */
+ y = temp2_y[flow_tail];
+ x = temp2_x[flow_tail];
+
+ /* Forget that entry */
+ if (++flow_tail == MAX_SHORT) flow_tail = 0;
+
+ /* Ignore too far entries */
+ //if (distance(ty, tx, y, x) > 100) continue;
+
+ /* Add the "children" */
+ for (d = 0; d < 8; d++)
+ {
+ /* Add that child if "legal" */
+ travel_flow_aux(y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x], wall);
+ }
+ }
+
+ /* Forget the flow info */
+ flow_head = flow_tail = 0;
+}
+
+/*!
+ * @brief トラベル処理のメインルーチン
+ * @return なし
+ */
+void do_cmd_travel(void)
+{
+ POSITION x, y;
+ int i;
+ POSITION dx, dy, sx, sy;
+ feature_type *f_ptr;
+
+ if (travel.x != 0 && travel.y != 0 &&
+ get_check(_("トラベルを継続しますか?", "Do you continue to travel?")))
+ {
+ y = travel.y;
+ x = travel.x;
+ }
+ else if (!tgt_pt(&x, &y)) return;
+
+ if ((x == p_ptr->x) && (y == p_ptr->y))
+ {
+ msg_print(_("すでにそこにいます!", "You are already there!!"));
+ return;
+ }
+
+ f_ptr = &f_info[grid_array[y][x].feat];
+
+ if ((grid_array[y][x].info & CAVE_MARK) &&
+ (have_flag(f_ptr->flags, FF_WALL) ||
+ have_flag(f_ptr->flags, FF_CAN_DIG) ||
+ (have_flag(f_ptr->flags, FF_DOOR) && grid_array[y][x].mimic)))
+ {
+ msg_print(_("そこには行くことができません!", "You cannot travel there!"));
+ return;
+ }
+
+ forget_travel_flow();
+ travel_flow(y, x);
+
+ travel.x = x;
+ travel.y = y;
+
+ /* Travel till 255 steps */
+ travel.run = 255;
+
+ /* Paranoia */
+ travel.dir = 0;
+
+ /* Decides first direction */
+ dx = abs(p_ptr->x - x);
+ dy = abs(p_ptr->y - y);
+ sx = ((x == p_ptr->x) || (dx < dy)) ? 0 : ((x > p_ptr->x) ? 1 : -1);
+ sy = ((y == p_ptr->y) || (dy < dx)) ? 0 : ((y > p_ptr->y) ? 1 : -1);
+
+ for (i = 1; i <= 9; i++)
+ {
+ if ((sx == ddx[i]) && (sy == ddy[i])) travel.dir = i;
+ }
+}
+#endif