OSDN Git Service

「`」キーで、指定した場所に自動移動するnethack風トラベルコマンドを実装。(from XAngband)
authoriks <iks@0568b783-4c39-0410-ac80-bf13821ea2a2>
Sat, 7 Mar 2009 23:04:53 +0000 (23:04 +0000)
committeriks <iks@0568b783-4c39-0410-ac80-bf13821ea2a2>
Sat, 7 Mar 2009 23:04:53 +0000 (23:04 +0000)
src/cave.c
src/cmd1.c
src/cmd2.c
src/defines.h
src/dungeon.c
src/externs.h
src/types.h
src/variable.c

index 6ed1a58..aa90ad0 100644 (file)
@@ -5044,6 +5044,20 @@ void disturb(int stop_search, int unused_flag)
                p_ptr->update |= (PU_FLOW);
        }
 
+#ifdef TRAVEL
+       if (travel.run)
+       {
+               /* Cancel */
+               travel.run = 0;
+
+               /* Check for new panel if appropriate */
+               if (center_player && !center_running) verify_panel();
+
+               /* Calculate torch radius */
+               p_ptr->update |= (PU_TORCH);
+       }
+#endif
+
        /* Flush the input if requested */
        if (flush_disturb) flush();
 }
index f2e0076..4ed6213 100644 (file)
@@ -4990,3 +4990,152 @@ void run_step(int dir)
                disturb(0, 0);
        }
 }
+
+
+#ifdef TRAVEL
+/*
+ * Test for traveling
+ */
+static bool travel_test(void)
+{
+       int prev_dir, new_dir, check_dir = 0;
+       int row, col;
+       int i, max;
+       bool stop = TRUE;
+       cave_type *c_ptr;
+
+       /* Where we came from */
+       prev_dir = find_prevdir;
+
+       /* Range of newly adjacent grids */
+       max = (prev_dir & 0x01) + 1;
+
+       for (i = 0; i < 8; i++)
+       {
+               if (travel.cost[py+ddy_ddd[i]][px+ddx_ddd[i]] < travel.cost[py][px]) stop = FALSE;
+       }
+
+       if (stop) return (TRUE);
+
+       /* break run when leaving trap detected region */
+       if ((disturb_trap_detect || alert_trap_detect)
+           && p_ptr->dtrap && !(cave[py][px].info & CAVE_IN_DETECT))
+       {
+               /* No duplicate warning */
+               p_ptr->dtrap = FALSE;
+
+               /* You are just on the edge */
+               if (!(cave[py][px].info & CAVE_UNSAFE))
+               {
+                       if (alert_trap_detect)
+                       {
+#ifdef JP
+                               msg_print("* Ãí°Õ:¤³¤ÎÀè¤Ï¥È¥é¥Ã¥×¤Î´¶ÃÎÈϰϳ°¤Ç¤¹¡ª *");
+#else
+                               msg_print("*Leaving trap detect region!*");
+#endif
+                       }
+
+                       if (disturb_trap_detect)
+                       {
+                               /* Break Run */
+                               return(TRUE);
+                       }
+               }
+       }
+
+       /* Cannot travel when blind */
+       if (p_ptr->blind || no_lite())
+       {
+#ifdef JP
+               msg_print("Ìܤ¬¸«¤¨¤Ê¤¤¡ª");
+#else
+               msg_print("You cannot see!");
+#endif
+               return (TRUE);
+       }
+
+       /* Look at every newly adjacent square. */
+       for (i = -max; i <= max; i++)
+       {
+               /* New direction */
+               new_dir = cycle[chome[prev_dir] + i];
+
+               /* New location */
+               row = py + ddy[new_dir];
+               col = px + ddx[new_dir];
+
+               /* Access grid */
+               c_ptr = &cave[row][col];
+
+
+               /* Visible monsters abort running */
+               if (c_ptr->m_idx)
+               {
+                       monster_type *m_ptr = &m_list[c_ptr->m_idx];
+
+                       /* Visible monster */
+                       if (m_ptr->ml) return (TRUE);
+               }
+       }
+
+       /* Failure */
+       return (FALSE);
+}
+
+
+/*
+ * Travel command
+ */
+void travel_step(void)
+{
+       int i;
+       int dir = travel.dir;
+       int old_run = travel.run;
+
+       find_prevdir = dir;
+
+       /* disturb */
+       if (travel_test())
+       {
+               if (travel.run == 255)
+               {
+#ifdef JP
+                       msg_print("Æ»¶Ú¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡ª");
+#else
+                       msg_print("No route is found!");
+#endif
+               }
+               disturb(0, 0);
+               return;
+       }
+
+       energy_use = 100;
+
+       for (i = 1; i <= 9; i++)
+       {
+               if (i == 5) continue;
+
+               if (travel.cost[py+ddy[i]][px+ddx[i]] < travel.cost[py+ddy[dir]][px+ddx[dir]])
+               {
+                       dir = i;
+               }
+       }
+
+       /* Close door */
+       if (!easy_open && is_closed_door(cave[py+ddy[dir]][px+ddx[dir]].feat))
+       {
+               disturb(0, 0);
+               return;
+       }
+
+       travel.dir = dir;
+       move_player(dir, always_pickup, easy_disarm);
+       travel.run = old_run;
+
+       if ((py == travel.y) && (px == travel.x))
+               travel.run = 0;
+       else
+               travel.run--;
+}
+#endif
index 95d7331..9e14b27 100644 (file)
@@ -4488,3 +4488,170 @@ void do_cmd_throw(void)
 {
        do_cmd_throw_aux(1, FALSE, 0);
 }
+
+
+#ifdef TRAVEL
+/*
+ * Hack: travel command
+ */
+#define TRAVEL_UNABLE 9999
+
+static int flow_head = 0;
+static int flow_tail = 0;
+static s16b temp2_x[MAX_SHORT];
+static s16b temp2_y[MAX_SHORT];
+
+/* Hack: forget the "flow" information */
+void forget_travel_flow(void)
+{
+       int x, y;
+
+       /* Check the entire dungeon */
+       for (y = 0; y < cur_hgt; y++)
+       {
+               for (x = 0; x < cur_wid; x++)
+               {
+                       /* Forget the old data */
+                       travel.cost[y][x] = TRAVEL_UNABLE;
+               }
+       }
+}
+
+static bool travel_flow_aux(int y, int x, int n, bool wall)
+{
+       cave_type *c_ptr = &cave[y][x];
+       feature_type *f_ptr = &f_info[c_ptr->feat];
+       int old_head = flow_head;
+
+       n = n % TRAVEL_UNABLE;
+
+       /* Ignore out of bounds */
+       if (!in_bounds(y, x)) return wall;
+
+       /* Ignore "pre-stamped" entries */
+       if (travel.cost[y][x] != TRAVEL_UNABLE) return wall;
+
+       /* 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) && cave[y][x].mimic) ||
+               (!have_flag(f_ptr->flags, FF_MOVE) && have_flag(f_ptr->flags, FF_CAN_FLY) && !p_ptr->levitation))
+       {
+               if (!wall) return wall;
+       }
+       else
+       {
+               wall = FALSE;
+       }
+
+       /* Save the flow cost */
+       travel.cost[y][x] = n;
+       if (wall) travel.cost[y][x] += TRAVEL_UNABLE;
+
+       /* 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 wall;
+}
+
+
+static void travel_flow(int ty, int tx)
+{
+       int x, y, d;
+       bool wall = FALSE;
+       feature_type *f_ptr = &f_info[cave[ty][tx].feat];
+
+       /* Reset the "queue" */
+       flow_head = flow_tail = 0;
+
+       if (!have_flag(f_ptr->flags, FF_MOVE)) wall = TRUE;
+
+       /* Add the player's grid to the queue */
+       wall = 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;
+
+               /* Add the "children" */
+               for (d = 0; d < 8; d++)
+               {
+                       /* Add that child if "legal" */
+                       wall = travel_flow_aux(y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x] + 1, wall);
+               }
+       }
+
+       /* Forget the flow info */
+       flow_head = flow_tail = 0;
+}
+
+void do_cmd_travel(void)
+{
+       int x, y, i;
+       int dx, dy, sx, sy;
+       feature_type *f_ptr;
+
+       if (!tgt_pt(&x, &y)) return;
+
+       if ((x == px) && (y == py))
+       {
+#ifdef JP
+               msg_print("¤¹¤Ç¤Ë¤½¤³¤Ë¤¤¤Þ¤¹¡ª");
+#else
+               msg_print("You are already there!!");
+#endif
+               return;
+       }
+
+       f_ptr = &f_info[cave[y][x].feat];
+
+       if ((cave[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) && cave[y][x].mimic)))
+       {
+#ifdef JP
+               msg_print("¤½¤³¤Ë¤Ï¹Ô¤¯¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡ª");
+#else
+               msg_print("You cannot travel there!");
+#endif
+               return;
+       }
+
+       travel.x = x;
+       travel.y = y;
+
+       forget_travel_flow();
+       travel_flow(y, x);
+
+       /* Travel till 255 steps */
+       travel.run = 255;
+
+       /* Paranoia */
+       travel.dir = 0;
+
+       /* Decides first direction */
+       dx = abs(px - x);
+       dy = abs(py - y);
+       sx = ((x == px) || (dx < dy)) ? 0 : ((x > px) ? 1 : -1);
+       sy = ((y == py) || (dy < dx)) ? 0 : ((y > py) ? 1 : -1);
+
+       for (i = 1; i <= 9; i++)
+       {
+               if ((sx == ddx[i]) && (sy == ddy[i])) travel.dir = i;
+       }
+}
+#endif
index 1f8394e..d42945e 100644 (file)
@@ -5468,3 +5468,8 @@ extern int PlayerUID;
  */
 #define SCROBJ_FAKE_OBJECT  0x00000001
 #define SCROBJ_FORCE_DETAIL 0x00000002
+
+/*
+ * For travel command (auto run)
+ */
+#define TRAVEL
index 4de3021..982e79f 100644 (file)
@@ -5310,6 +5310,14 @@ msg_print("
                        break;
                }
 
+#ifdef TRAVEL
+               case '`':
+               {
+                       do_cmd_travel();
+                       break;
+               }
+#endif
+
                /* Hack -- Unknown command */
                default:
                {
@@ -5791,6 +5799,15 @@ msg_print("
                        run_step(0);
                }
 
+#ifdef TRAVEL
+               /* Traveling */
+               else if (travel.run)
+               {
+                       /* Take a step */
+                       travel_step();
+               }
+#endif
+
                /* Repeated command */
                else if (command_rep)
                {
index 327ce6b..bd9e263 100644 (file)
@@ -708,6 +708,9 @@ extern bool move_player_effect(int ny, int nx, u32b mpe_mode);
 extern bool trap_can_be_ignored(int feat);
 extern void move_player(int dir, bool do_pickup, bool break_trap);
 extern void run_step(int dir);
+#ifdef TRAVEL
+extern void travel_step(void);
+#endif
 
 /* cmd2.c */
 extern void do_cmd_go_up(void);
@@ -728,6 +731,9 @@ extern void do_cmd_fire(void);
 extern void do_cmd_fire_aux(int item, object_type *j_ptr);
 extern void do_cmd_throw(void);
 extern bool do_cmd_throw_aux(int mult, bool boomerang, int shuriken);
+#ifdef TRAVEL
+extern void do_cmd_travel(void);
+#endif
 
 /* cmd3.c */
 extern void do_cmd_inven(void);
@@ -1724,3 +1730,7 @@ extern void flush_ringbuf(void);
 extern void prepare_chuukei_hooks(void);
 #endif
 
+#ifdef TRAVEL
+/* for travel */
+extern travel_type travel;
+#endif
index 21252b7..8b3770a 100644 (file)
@@ -1689,3 +1689,17 @@ typedef struct
        s16b jammed[MAX_LJ_DOORS];
        s16b num_jammed;
 } door_type;
+
+
+#ifdef TRAVEL
+/*
+ *  A structure type for travel command
+ */
+typedef struct {
+       int run;
+       int cost[MAX_HGT][MAX_WID];
+       int x;
+       int y;
+       int dir;
+} travel_type;
+#endif
index 321d0d5..a752595 100644 (file)
@@ -1287,3 +1287,8 @@ bool chuukei_client;
 char *server_name;
 int server_port;
 #endif
+
+#ifdef TRAVEL
+/* for travel */
+travel_type travel;
+#endif