OSDN Git Service

[Refactor] #37353 トラベル処理の関数を player-move.c にまとめる。 / Move travel functions to player...
[hengband/hengband.git] / src / player-move.c
index fd2e7b3..c95201a 100644 (file)
@@ -2254,3 +2254,242 @@ void travel_step(void)
        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