OSDN Git Service

モンスターの追跡ルーチン関係をOを参考に大幅に変更。かなりの処理速度アップに繋がるはず。
authorhabu <habu@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 22 Jan 2002 18:12:08 +0000 (18:12 +0000)
committerhabu <habu@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 22 Jan 2002 18:12:08 +0000 (18:12 +0000)
src/cave.c
src/dungeon.c
src/externs.h
src/melee2.c

index 2ba87d2..e090930 100644 (file)
@@ -4223,54 +4223,6 @@ void forget_flow(void)
 
 
 /*
- * Hack -- Allow us to treat the "seen" array as a queue
- */
-static int flow_head = 0;
-static int flow_tail = 0;
-
-
-/*
- * Take note of a reachable grid.  Assume grid is legal.
- */
-static void update_flow_aux(int y, int x, int m, int n)
-{
-       cave_type *c_ptr;
-
-       int old_head = flow_head;
-
-
-       /* Get the grid */
-       c_ptr = &cave[y][x];
-
-       /* Ignore "pre-stamped" entries */
-       if (c_ptr->when == flow_n && (c_ptr->dist <= n) && (c_ptr->cost <= m)) return;
-
-       /* Ignore "walls" and "rubble" */
-       if ((c_ptr->feat > FEAT_SECRET) && (c_ptr->feat != FEAT_TREES) && !cave_floor_grid(c_ptr)) return;
-
-       /* Save the flow cost */
-       if (c_ptr->when != flow_n || c_ptr->cost > m) c_ptr->cost = m;
-       if (c_ptr->when != flow_n || c_ptr->dist > n) c_ptr->dist = n;
-
-       /* Save the time-stamp */
-       c_ptr->when = flow_n;
-
-       /* Hack -- limit flow depth */
-       if (n == MONSTER_FLOW_DEPTH) return;
-
-       /* Enqueue that entry */
-       temp_y[flow_head] = y;
-       temp_x[flow_head] = x;
-
-       /* Advance the queue */
-       if (++flow_head == TEMP_MAX) flow_head = 0;
-
-       /* Hack -- notice overflow by forgetting new entry */
-       if (flow_head == flow_tail) flow_head = old_head;
-}
-
-
-/*
  * Hack - speed up the update_flow algorithm by only doing
  * it everytime the player moves out of LOS of the last
  * "way-point".
@@ -4296,6 +4248,8 @@ static u16b flow_y = 0;
 void update_flow(void)
 {
        int x, y, d;
+       int flow_head = 1;
+       int flow_tail = 0;
 
        /* Hack -- disabled */
        if (stupid_monsters) return;
@@ -4303,23 +4257,126 @@ void update_flow(void)
        /* Paranoia -- make sure the array is empty */
        if (temp_n) return;
 
-#if 0
        /* The last way-point is on the map */
        if (running && in_bounds(flow_y, flow_x))
        {
                /* The way point is in sight - do not update.  (Speedup) */
                if (cave[flow_y][flow_x].info & CAVE_VIEW) return;
        }
-#endif
+
+       /* Erase all of the current flow information */
+       for (y = 0; y < cur_hgt; y++)
+       {
+               for (x = 0; x < cur_wid; x++)
+               {
+                       cave[y][x].cost = 0;
+                       cave[y][x].dist = 0;
+               }
+       }
 
        /* Save player position */
        flow_y = py;
        flow_x = px;
 
-       /* Cycle the old entries (once per 128 updates) */
-       if (flow_n == 255)
+       /* Add the player's grid to the queue */
+       temp_y[0] = py;
+       temp_x[0] = px;
+
+       /* Now process the queue */
+       while (flow_head != flow_tail)
+       {
+               int ty, tx;
+
+               /* Extract the next entry */
+               ty = temp_y[flow_tail];
+               tx = temp_x[flow_tail];
+
+               /* Forget that entry */
+               if (++flow_tail == TEMP_MAX) flow_tail = 0;
+
+               /* Add the "children" */
+               for (d = 0; d < 8; d++)
+               {
+                       int old_head = flow_head;
+                       int m = cave[ty][tx].cost + 1;
+                       int n = cave[ty][tx].dist + 1;
+                       cave_type *c_ptr;
+
+                       /* Child location */
+                       y = ty + ddy_ddd[d];
+                       x = tx + ddx_ddd[d];
+
+                       /* Ignore player's grid */
+                       if (x == px && y == py) continue;
+
+                       c_ptr = &cave[y][x];
+                                      
+                       if ((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_SECRET)) m += 3;
+
+                       /* Ignore "pre-stamped" entries */
+                       if (c_ptr->dist != 0 && c_ptr->dist <= n && c_ptr->cost <= m) continue;
+
+                       /* Ignore "walls" and "rubble" */
+                       if ((c_ptr->feat > FEAT_SECRET) && (c_ptr->feat != FEAT_TREES) && !cave_floor_grid(c_ptr)) continue;
+
+                       /* Save the flow cost */
+                       if (c_ptr->cost == 0 || c_ptr->cost > m) c_ptr->cost = m;
+                       if (c_ptr->dist == 0 || c_ptr->dist > n) c_ptr->dist = n;
+
+                       /* Hack -- limit flow depth */
+                       if (n == MONSTER_FLOW_DEPTH) continue;
+
+                       /* Enqueue that entry */
+                       temp_y[flow_head] = y;
+                       temp_x[flow_head] = x;
+
+                       /* Advance the queue */
+                       if (++flow_head == TEMP_MAX) flow_head = 0;
+
+                       /* Hack -- notice overflow by forgetting new entry */
+                       if (flow_head == flow_tail) flow_head = old_head;
+               }
+       }
+}
+
+
+static int scent_when = 0;
+
+/*
+ * Characters leave scent trails for perceptive monsters to track.
+ *
+ * Smell is rather more limited than sound.  Many creatures cannot use 
+ * it at all, it doesn't extend very far outwards from the character's 
+ * current position, and monsters can use it to home in the character, 
+ * but not to run away from him.
+ *
+ * Smell is valued according to age.  When a character takes his turn, 
+ * scent is aged by one, and new scent of the current age is laid down.  
+ * Speedy characters leave more scent, true, but it also ages faster, 
+ * which makes it harder to hunt them down.
+ *
+ * Whenever the age count loops, most of the scent trail is erased and 
+ * the age of the remainder is recalculated.
+ */
+void update_smell(void)
+{
+       int i, j;
+       int y, x;
+
+       /* Create a table that controls the spread of scent */
+       int scent_adjust[5][5] = 
+       {
+               { 250,  0,  0,  0, 250 },
+               {   0,  1,  1,  1,   0 },
+               {   0,  1,  2,  1,   0 },
+               {   0,  1,  1,  1,   0 },
+               { 250,  0,  0,  0, 250 },
+       };
+
+       /* Loop the age and adjust scent values when necessary */
+       if (scent_when++ == 250)
        {
-               /* Rotate the time-stamps */
+               /* Scan the entire dungeon */
                for (y = 0; y < cur_hgt; y++)
                {
                        for (x = 0; x < cur_wid; x++)
@@ -4330,48 +4387,42 @@ void update_flow(void)
                }
 
                /* Restart */
-               flow_n = 127;
+               scent_when = 127;
        }
 
-       /* Start a new flow (never use "zero") */
-       flow_n++;
 
+       /* Lay down new scent */
+       for (i = 0; i < 5; i++)
+       {
+               for (j = 0; j < 5; j++)
+               {
+                       cave_type *c_ptr;
 
-       /* Reset the "queue" */
-       flow_head = flow_tail = 0;
+                       /* Translate table to map grids */
+                       y = i + py - 2;
+                       x = j + px - 2;
 
-       /* Add the player's grid to the queue */
-       update_flow_aux(py, px, 0, 0);
+                       /* Check Bounds */
+                       if (!in_bounds(y, x)) continue;
 
-       /* Now process the queue */
-       while (flow_head != flow_tail)
-       {
-               /* Extract the next entry */
-               y = temp_y[flow_tail];
-               x = temp_x[flow_tail];
+                       c_ptr = &cave[y][x];
 
-               /* Forget that entry */
-               if (++flow_tail == TEMP_MAX) flow_tail = 0;
+                       /* Walls, water, and lava cannot hold scent. */
+                       if ((c_ptr->feat > FEAT_SECRET) && (c_ptr->feat != FEAT_TREES) && !cave_floor_grid(c_ptr)) continue;
 
-               /* Add the "children" */
-               for (d = 0; d < 8; d++)
-               {
-                       int tmp = cave[y][x].cost+1;
-                       int yy = y+ddy_ddd[d];
-                       int xx = x+ddx_ddd[d];
+                       /* Grid must not be blocked by walls from the character */
+                       if (!player_has_los_bold(y, x)) continue;
+
+                       /* Note grids that are too far away */
+                       if (scent_adjust[i][j] == 250) continue;
 
-                       if ((cave[yy][xx].feat >= FEAT_DOOR_HEAD) && (cave[yy][xx].feat <= FEAT_SECRET)) tmp += 3;
-                       /* Add that child if "legal" */
-                       update_flow_aux(yy, xx, tmp, cave[y][x].dist+1);
+                       /* Mark the grid with new scent */
+                       c_ptr->when = scent_when + scent_adjust[i][j];
                }
        }
-
-       /* Forget the flow info */
-       flow_head = flow_tail = 0;
 }
 
 
-
 /*
  * Hack -- map the current panel (plus some) ala "magic mapping"
  */
index 601d637..0b53594 100644 (file)
@@ -5455,6 +5455,9 @@ msg_format("%s(%c)
                /* Handle "leaving" */
                if (p_ptr->leaving) break;
        }
+
+       /* Update scent trail */
+       update_smell();
 }
 
 
index d2ccf9d..32a76be 100644 (file)
@@ -572,6 +572,7 @@ extern void update_mon_lite(void);
 extern void clear_mon_lite(void);
 extern void forget_flow(void);
 extern void update_flow(void);
+extern void update_smell(void);
 extern void map_area(int range);
 extern void wiz_lite(bool wizard, bool ninja);
 extern void wiz_dark(void);
index aeccf78..58ce038 100644 (file)
@@ -524,9 +524,11 @@ static int mon_will_run(int m_idx)
  */
 static bool get_moves_aux(int m_idx, int *yp, int *xp)
 {
-       int i, y, x, y1, x1, when = 0, cost = 999;
+       int i, y, x, y1, x1, best;
 
        cave_type *c_ptr;
+       bool use_sound = FALSE;
+       bool use_scent = FALSE;
 
        monster_type *m_ptr = &m_list[m_idx];
        monster_race *r_ptr = &r_info[m_ptr->r_idx];
@@ -543,27 +545,38 @@ static bool get_moves_aux(int m_idx, int *yp, int *xp)
        y1 = m_ptr->fy;
        x1 = m_ptr->fx;
 
+       /* Hack -- Player can see us, run towards him */
+       if (player_has_los_bold(y1, x1)) return (FALSE);
+
        /* Monster grid */
        c_ptr = &cave[y1][x1];
 
-       /* The player is not currently near the monster grid */
-       if (c_ptr->when < cave[py][px].when)
+       /* If we can hear noises, advance towards them */
+       if (c_ptr->cost)
        {
-               /* The player has never been near the monster grid */
-               if (!c_ptr->when) return (FALSE);
+               use_sound = TRUE;
+               best = 999;
        }
 
-       if (c_ptr->dist > MONSTER_FLOW_DEPTH) return (FALSE);
-       if ((c_ptr->dist > r_ptr->aaf) && !m_ptr->target_y) return (FALSE);
+       /* Otherwise, try to follow a scent trail */
+       else if (c_ptr->when)
+       {
+               /* Too old smell */
+               if (cave[py][px].when - c_ptr->when > 127) return (FALSE);
 
-       /* Hack -- Player can see us, run towards him */
-       if (player_has_los_bold(y1, x1)) return (FALSE);
+               use_scent = TRUE;
+               best = 0;
+       }
+
+       /* Otherwise, advance blindly */
+       else
+       {
+               return (FALSE);
+       }
 
        /* Check nearby grids, diagonals first */
        for (i = 7; i >= 0; i--)
        {
-               int value;
-
                /* Get the location */
                y = y1 + ddy_ddd[i];
                x = x1 + ddx_ddd[i];
@@ -573,22 +586,29 @@ static bool get_moves_aux(int m_idx, int *yp, int *xp)
 
                c_ptr = &cave[y][x];
 
-               /* Ignore illegal locations */
-               if (!c_ptr->when) continue;
+               /* We're following a scent trail */
+               if (use_scent)
+               {
+                       int when = c_ptr->when;
 
-               /* Ignore ancient locations */
-               if (c_ptr->when < when) continue;
+                       /* Accept younger scent */
+                       if (best > when) continue;
+                       best = when;
+               }
 
-               if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
-                       value = c_ptr->dist;
-               else value = c_ptr->cost;
+               /* We're using sound */
+               else
+               {
+                       int cost;
 
-               /* Ignore distant locations */
-               if (value > cost) continue;
+                       if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
+                               cost = c_ptr->dist;
+                       else cost = c_ptr->cost;
 
-               /* Save the cost and time */
-               when = c_ptr->when;
-               cost = value;
+                       /* Accept louder sounds */
+                       if ((cost == 0) || (best < cost)) continue;
+                       best = cost;
+               }
 
                /* Hack -- Save the "twiddled" location */
                (*yp) = py + 16 * ddy_ddd[i];
@@ -596,7 +616,7 @@ static bool get_moves_aux(int m_idx, int *yp, int *xp)
        }
 
        /* No legal move (?) */
-       if (!when) return (FALSE);
+       if (best == 999 || best == 0) return (FALSE);
 
        /* Success */
        return (TRUE);
@@ -613,11 +633,10 @@ static bool get_moves_aux(int m_idx, int *yp, int *xp)
 static bool get_fear_moves_aux(int m_idx, int *yp, int *xp)
 {
        int y, x, y1, x1, fy, fx, gy = 0, gx = 0;
-       int when = 0, score = -1;
+       int dist = 0, score = -1;
        int i;
 
        monster_type *m_ptr = &m_list[m_idx];
-       monster_race *r_ptr = &r_info[m_ptr->r_idx];
 
        /* Monster flowing disabled */
        if (stupid_monsters) return (FALSE);
@@ -630,17 +649,6 @@ static bool get_fear_moves_aux(int m_idx, int *yp, int *xp)
        y1 = fy - (*yp);
        x1 = fx - (*xp);
 
-       /* The player is not currently near the monster grid */
-       if (cave[fy][fx].when < cave[py][px].when)
-       {
-               /* No reason to attempt flowing */
-               return (FALSE);
-       }
-
-       /* Monster is too far away to use flow information */
-       if (cave[fy][fx].dist > MONSTER_FLOW_DEPTH) return (FALSE);
-       if ((cave[fy][fx].dist > r_ptr->aaf) && !m_ptr->target_y) return (FALSE);
-
        /* Check nearby grids, diagonals first */
        for (i = 7; i >= 0; i--)
        {
@@ -653,11 +661,7 @@ static bool get_fear_moves_aux(int m_idx, int *yp, int *xp)
                /* Ignore locations off of edge */
                if (!in_bounds2(y, x)) continue;
 
-               /* Ignore illegal locations */
-               if (cave[y][x].when == 0) continue;
-
-               /* Ignore ancient locations */
-               if (cave[y][x].when < when) continue;
+               if (cave[y][x].dist < dist) continue;
 
                /* Calculate distance of this grid from our destination */
                dis = distance(y, x, y1, x1);
@@ -672,7 +676,7 @@ static bool get_fear_moves_aux(int m_idx, int *yp, int *xp)
                if (s < score) continue;
 
                /* Save the score and time */
-               when = cave[y][x].when;
+               dist = cave[y][x].dist;
                score = s;
 
                /* Save the location */
@@ -681,7 +685,7 @@ static bool get_fear_moves_aux(int m_idx, int *yp, int *xp)
        }
 
        /* No legal move (?) */
-       if (!when) return (FALSE);
+       if (score == -1) return (FALSE);
 
        /* Find deltas */
        (*yp) = fy - gy;