/*
- * 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".
void update_flow(void)
{
int x, y, d;
+ int flow_head = 1;
+ int flow_tail = 0;
/* Hack -- disabled */
if (stupid_monsters) return;
/* 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++)
}
/* 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"
*/
*/
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];
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];
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];
}
/* No legal move (?) */
- if (!when) return (FALSE);
+ if (best == 999 || best == 0) return (FALSE);
/* Success */
return (TRUE);
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);
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--)
{
/* 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);
if (s < score) continue;
/* Save the score and time */
- when = cave[y][x].when;
+ dist = cave[y][x].dist;
score = s;
/* Save the location */
}
/* No legal move (?) */
- if (!when) return (FALSE);
+ if (score == -1) return (FALSE);
/* Find deltas */
(*yp) = fy - gy;