OSDN Git Service

フオツフ、ヒツソ、、ネ豕モ、ャ、「、テ、ソノャ、ホス、タオ.
[hengband/hengband.git] / src / cave.c
index 84fb1bf..ca9c170 100644 (file)
@@ -445,10 +445,11 @@ bool player_can_see_bold(int y, int x)
        /* Require line of sight to the grid */
        if (!player_has_los_bold(y, x)) return (FALSE);
 
-       if (p_ptr->pclass == CLASS_NINJA) return TRUE;
+       /* Noctovision of Ninja */
+       if (p_ptr->see_nocto) return TRUE;
 
        /* Require "perma-lite" of the grid */
-       if (!(c_ptr->info & (CAVE_GLOW | CAVE_MNLT))) return (FALSE);
+       if (!(c_ptr->info & CAVE_MNLT) && ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)) return FALSE;
 
        /* Floors are simple */
        if (cave_floor_bold(y, x)) return (TRUE);
@@ -458,7 +459,7 @@ bool player_can_see_bold(int y, int x)
        xx = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
 
        /* Check for "local" illumination */
-       if (cave[yy][xx].info & (CAVE_GLOW | CAVE_MNLT))
+       if ((cave[yy][xx].info & CAVE_MNLT) || ((cave[yy][xx].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW))
        {
                /* Assume the wall is really illuminated */
                return (TRUE);
@@ -749,6 +750,65 @@ static byte lighting_colours[16][2] =
        {TERM_L_UMBER, TERM_UMBER}
 };
 
+
+/*
+ * Mega-Hack -- Partial code of map_info() for darkened grids
+ * Note: Each variable is declared in map_info().
+ *       This macro modifies "feat", "f_ptr", "c" and "a".
+ */
+#define darkened_grid_hack() \
+{ \
+       if (feat_floor(feat)) \
+       { \
+               /* Unsafe cave grid -- idea borrowed from Unangband */ \
+               if (view_unsafe_grids && (c_ptr->info & CAVE_UNSAFE)) \
+               { \
+                       feat = FEAT_UNDETECTD; \
+\
+                       /* Access unsafe darkness */ \
+                       f_ptr = &f_info[feat]; \
+\
+                       /* Char and attr of unsafe grid */ \
+                       c = f_ptr->x_char; \
+                       a = f_ptr->x_attr; \
+               } \
+               else \
+               { \
+                       /* For feat_priority control */ \
+                       feat = FEAT_NONE; \
+\
+                       if (use_graphics) \
+                       { \
+                               /* Access darkness */ \
+                               f_ptr = &f_info[feat]; \
+\
+                               /* Char and attr of darkness */ \
+                               c = f_ptr->x_char; \
+                               a = f_ptr->x_attr; \
+                       } \
+                       else \
+                       { \
+                               /* Use "black" */ \
+                               a = TERM_DARK; \
+                       } \
+               } \
+       } \
+       else \
+       { \
+               if (is_ascii_graphics(a)) \
+               { \
+                       /* Use darkened colour */ \
+                       a = !new_ascii_graphics ? TERM_L_DARK : lighting_colours[a][1]; \
+               } \
+               else if (use_graphics && feat_supports_lighting(feat)) \
+               { \
+                       /* Use a dark tile */ \
+                       c++; \
+               } \
+       } \
+} ;
+
+
 /*
  * Extract the attr/char to display at the given (legal) map location
  *
@@ -873,32 +933,32 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp)
 void map_info(int y, int x, byte *ap, char *cp)
 #endif /* USE_TRANSPARENCY */
 {
-       cave_type *c_ptr;
+       /* Get the cave */
+       cave_type *c_ptr = &cave[y][x];
 
        feature_type *f_ptr;
 
        s16b this_o_idx, next_o_idx = 0;
 
-       byte feat;
+       /* Feature code (applying "mimic" field) */
+       byte feat = c_ptr->mimic ? c_ptr->mimic : f_info[c_ptr->feat].mimic;
 
        byte a;
        byte c;
 
-       /* Get the cave */
-       c_ptr = &cave[y][x];
-
-       /* Feature code (applying "mimic" field) */
-       feat = c_ptr->mimic ? c_ptr->mimic : f_info[c_ptr->feat].mimic;
+       /* Is this grid "darkened" by monster? */
+       bool darkened_grid = ((c_ptr->info & (CAVE_VIEW | CAVE_LITE | CAVE_MNLT | CAVE_MNDK)) == (CAVE_VIEW | CAVE_MNDK)) &&
+                                                       !p_ptr->see_nocto && !p_ptr->blind;
 
        /* Floors (etc) */
        if ((feat <= FEAT_INVIS) || (feat == FEAT_DIRT) || (feat == FEAT_GRASS))
        {
                /* Memorized (or visible) floor */
-               if   ((c_ptr->info & CAVE_MARK) ||
-                   (((c_ptr->info & CAVE_LITE) || (c_ptr->info & CAVE_MNLT) ||
-                    ((c_ptr->info & CAVE_GLOW) &&
-                     (c_ptr->info & CAVE_VIEW))) &&
-                    !p_ptr->blind))
+               if ((c_ptr->info & CAVE_MARK) ||
+                 (((c_ptr->info & (CAVE_LITE | CAVE_MNLT)) ||
+                  ((c_ptr->info & CAVE_VIEW) &&
+                 (((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) || p_ptr->see_nocto))) &&
+                  !p_ptr->blind))
                {
                        /* Access floor */
                        f_ptr = &f_info[feat];
@@ -909,8 +969,14 @@ void map_info(int y, int x, byte *ap, char *cp)
                        /* Normal attr */
                        a = f_ptr->x_attr;
 
+                       /* Mega-Hack -- Handle "in-sight" and "darkened" grids first */
+                       if (darkened_grid)
+                       {
+                               darkened_grid_hack();
+                       }
+
                        /* Special lighting effects */
-                       if (view_special_lite && (!p_ptr->wild_mode) && ((a == TERM_WHITE) || use_graphics))
+                       else if (view_special_lite && (!p_ptr->wild_mode) && ((a == TERM_WHITE) || use_graphics))
                        {
                                /* Handle "blind" */
                                if (p_ptr->blind)
@@ -921,7 +987,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                                 * feat_supports_lighting(feat)
                                                 * is always TRUE here
                                                 */
-                                               
+
                                                /* Use a dark tile */
                                                c++;
                                        }
@@ -957,7 +1023,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                }
 
                                /* Handle "dark" grids */
-                               else if (!(c_ptr->info & CAVE_GLOW))
+                               else if ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
                                {
                                        if (use_graphics)
                                        {
@@ -1037,7 +1103,13 @@ void map_info(int y, int x, byte *ap, char *cp)
                        /* Normal attr */
                        a = f_ptr->x_attr;
 
-                       if (new_ascii_graphics)
+                       /* Mega-Hack -- Handle "in-sight" and "darkened" grids first */
+                       if (darkened_grid)
+                       {
+                               darkened_grid_hack();
+                       }
+
+                       else if (new_ascii_graphics)
                        {
                                /* Handle "blind" */
                                if (p_ptr->blind)
@@ -1093,7 +1165,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                        }
 
                                        /* Not glowing */
-                                       else if (!(c_ptr->info & CAVE_GLOW))
+                                       else if ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
                                        {
                                                if (is_ascii_graphics(a))
                                                {
@@ -1103,6 +1175,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                        }
                                }
                        }
+
                        /* Special lighting effects */
                        else if (view_granite_lite && !p_ptr->wild_mode &&
                           (((a == TERM_WHITE) && !use_graphics) ||
@@ -1161,7 +1234,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                        }
 
                                        /* Not glowing */
-                                       else if (!(c_ptr->info & CAVE_GLOW))
+                                       else if ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
                                        {
                                                if (use_graphics)
                                                {
@@ -1184,7 +1257,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                                xx = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
 
                                                /* Check for "local" illumination */
-                                               if (!(cave[yy][xx].info & CAVE_GLOW))
+                                               if ((cave[yy][xx].info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
                                                {
                                                        if (use_graphics)
                                                        {
@@ -1222,6 +1295,12 @@ void map_info(int y, int x, byte *ap, char *cp)
 
                        /* Normal char */
                        c = f_ptr->x_char;
+
+                       /* Mega-Hack -- Handle "in-sight" and "darkened" grids */
+                       if (darkened_grid)
+                       {
+                               darkened_grid_hack();
+                       }
                }
        }
 
@@ -1417,7 +1496,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                 * Monsters with both CHAR_CLEAR and ATTR_CLEAR
                                 * flags are always unseen.
                                 */
-                               if (!(~r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)))
+                               if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
                                {
                                        /* Do nothing */
                                }
@@ -1446,7 +1525,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                 * Monsters with both CHAR_CLEAR and ATTR_CLEAR
                                 * flags are always unseen.
                                 */
-                               else if (!(~r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)))
+                               else if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
                                {
                                        /* Do nothing */
                                }
@@ -1454,7 +1533,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                else
                                {
                                        /***  Monster's attr  ***/
-                                       if ((r_ptr->flags1 & RF1_ATTR_CLEAR) && !use_graphics)
+                                       if ((r_ptr->flags1 & RF1_ATTR_CLEAR) && (*ap != TERM_DARK) && !use_graphics)
                                        {
                                                /* Clear-attr */
                                                /* Do nothing */
@@ -1486,7 +1565,7 @@ void map_info(int y, int x, byte *ap, char *cp)
                                        }
 
                                        /***  Monster's char  ***/
-                                       if ((r_ptr->flags1 & RF1_CHAR_CLEAR) && !use_graphics)
+                                       if ((r_ptr->flags1 & RF1_CHAR_CLEAR) && (*cp != ' ') && !use_graphics)
                                        {
                                                /* Clear-char */
                                                /* Do nothing */
@@ -1517,7 +1596,7 @@ void map_info(int y, int x, byte *ap, char *cp)
        }
 
        /* Handle "player" */
-       if ((y == py) && (x == px))
+       if (player_bold(y, x))
        {
                monster_race *r_ptr = &r_info[0];
 
@@ -1690,10 +1769,11 @@ void note_spot(int y, int x)
                /* Require line of sight to the grid */
                if (!(c_ptr->info & (CAVE_VIEW))) return;
 
-               if (p_ptr->pclass != CLASS_NINJA)
-               {
                /* Require "perma-lite" of the grid */
-               if (!(c_ptr->info & (CAVE_GLOW | CAVE_MNLT))) return;
+               if (!(c_ptr->info & CAVE_MNLT) && ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW))
+               {
+                       /* Not Ninja */
+                       if (!p_ptr->see_nocto) return;
                }
        }
 
@@ -1714,22 +1794,19 @@ void note_spot(int y, int x)
        /* Hack -- memorize grids */
        if (!(c_ptr->info & (CAVE_MARK)))
        {
-               if (p_ptr->pclass == CLASS_NINJA)
-               {
-                       c_ptr->info |= (CAVE_MARK);
-               }
                /* Handle floor grids first */
                if ((feat <= FEAT_INVIS) || (feat == FEAT_DIRT) || (feat == FEAT_GRASS))
                {
                        /* Option -- memorize all torch-lit floors */
-                       if (view_torch_grids && (c_ptr->info & (CAVE_LITE | CAVE_MNLT)))
+                       if (view_torch_grids &&
+                           ((c_ptr->info & (CAVE_LITE | CAVE_MNLT)) || p_ptr->see_nocto))
                        {
                                /* Memorize */
                                c_ptr->info |= (CAVE_MARK);
                        }
 
                        /* Option -- memorize all perma-lit floors */
-                       else if (view_perma_grids && (c_ptr->info & (CAVE_GLOW)))
+                       else if (view_perma_grids && ((c_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW))
                        {
                                /* Memorize */
                                c_ptr->info |= (CAVE_MARK);
@@ -1750,6 +1827,13 @@ void note_spot(int y, int x)
                        c_ptr->info |= (CAVE_MARK);
                }
 
+               /* Memorize walls seen by noctovision of Ninja */
+               else if (p_ptr->see_nocto)
+               {
+                       /* Memorize */
+                       c_ptr->info |= (CAVE_MARK);
+               }
+
                /* Memorize certain non-torch-lit wall grids */
                else
                {
@@ -1760,7 +1844,7 @@ void note_spot(int y, int x)
                        xx = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
 
                        /* Check for "local" illumination */
-                       if (cave[yy][xx].info & (CAVE_GLOW))
+                       if ((cave[yy][xx].info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW)
                        {
                                /* Memorize */
                                c_ptr->info |= (CAVE_MARK);
@@ -2816,6 +2900,30 @@ void forget_lite(void)
 
 
 /*
+ * For delayed visual update
+ */
+#define cave_note_and_redraw_later(C,Y,X) \
+{\
+       (C)->info |= CAVE_NOTE; \
+       cave_redraw_later((C), (Y), (X)); \
+}
+
+
+/*
+ * For delayed visual update
+ */
+#define cave_redraw_later(C,Y,X) \
+{\
+       if (!((C)->info & CAVE_REDRAW)) \
+       { \
+               (C)->info |= CAVE_REDRAW; \
+               redraw_y[redraw_n] = (Y); \
+               redraw_x[redraw_n++] = (X); \
+       } \
+}
+
+
+/*
  * XXX XXX XXX
  *
  * This macro allows us to efficiently add a grid to the "lite" array,
@@ -2861,6 +2969,7 @@ void update_lite(void)
 {
        int i, x, y, min_x, max_x, min_y, max_y;
        int p = p_ptr->cur_lite;
+       cave_type *c_ptr;
 
        /*** Special case ***/
 
@@ -2871,8 +2980,8 @@ void update_lite(void)
                /* Forget the old lite */
                /* forget_lite(); Perhaps don't need? */
 
-               /* Draw the player */
-               lite_spot(py, px);
+               /* Add it to later visual update */
+               cave_redraw_later(&cave[py][px], py, px);
        }
 #endif
 
@@ -3041,14 +3150,13 @@ void update_lite(void)
                y = lite_y[i];
                x = lite_x[i];
 
-               /* Update fresh grids */
-               if (cave[y][x].info & (CAVE_TEMP)) continue;
+               c_ptr = &cave[y][x];
 
-               /* Note */
-               note_spot(y, x);
+               /* Update fresh grids */
+               if (c_ptr->info & (CAVE_TEMP)) continue;
 
-               /* Redraw */
-               lite_spot(y, x);
+               /* Add it to later visual update */
+               cave_note_and_redraw_later(c_ptr, y, x);
        }
 
        /* Clear them all */
@@ -3057,22 +3165,28 @@ void update_lite(void)
                y = temp_y[i];
                x = temp_x[i];
 
+               c_ptr = &cave[y][x];
+
                /* No longer in the array */
-               cave[y][x].info &= ~(CAVE_TEMP);
+               c_ptr->info &= ~(CAVE_TEMP);
 
                /* Update stale grids */
-               if (cave[y][x].info & (CAVE_LITE)) continue;
+               if (c_ptr->info & (CAVE_LITE)) continue;
 
-               /* Redraw */
-               lite_spot(y, x);
+               /* Add it to later visual update */
+               cave_redraw_later(c_ptr, y, x);
        }
 
        /* None left */
        temp_n = 0;
+
+       /* Mega-Hack -- Visual update later */
+       p_ptr->update |= (PU_DELAY_VIS);
 }
 
 
 static bool mon_invis;
+static s16b mon_fy, mon_fx;
 
 /*
  * Add a square to the changes array
@@ -3080,40 +3194,162 @@ static bool mon_invis;
 static void mon_lite_hack(int y, int x)
 {
        cave_type *c_ptr;
+       int       midpoint, dpf, d;
 
-       /* Out of bounds */
-       if (!in_bounds2(y, x)) return;
+       /* We trust this grid is in bounds */
+       /* if (!in_bounds2(y, x)) return; */
 
        c_ptr = &cave[y][x];
 
        /* Want a unlit square in view of the player */
        if ((c_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
 
-       /* Hack XXX XXX - Is it a wall and monster not in LOS? */
-       if (!cave_floor_grid(c_ptr) && mon_invis) return;
+       if (!cave_floor_grid(c_ptr))
+       {
+               /* Hack XXX XXX - Is it a wall and monster not in LOS? */
+               if (mon_invis) return;
 
-       /* Save this square */
-       if (temp_n < TEMP_MAX)
+               /* Hack -- Prevent monster lite leakage in walls */
+
+               /* Horizontal walls between player and a monster */
+               if (((y < py) && (y > mon_fy)) || ((y > py) && (y < mon_fy)))
+               {
+                       dpf = py - mon_fy;
+                       d = y - mon_fy;
+                       midpoint = mon_fx + ((px - mon_fx) * ABS(d)) / ABS(dpf);
+
+                       /* Only first wall viewed from mid-x is lit */
+                       if (x < midpoint)
+                       {
+                               if (!cave_floor_bold(y, x + 1)) return;
+                       }
+                       else if (x > midpoint)
+                       {
+                               if (!cave_floor_bold(y, x - 1)) return;
+                       }
+               }
+
+               /* Vertical walls between player and a monster */
+               if (((x < px) && (x > mon_fx)) || ((x > px) && (x < mon_fx)))
+               {
+                       dpf = px - mon_fx;
+                       d = x - mon_fx;
+                       midpoint = mon_fy + ((py - mon_fy) * ABS(d)) / ABS(dpf);
+
+                       /* Only first wall viewed from mid-y is lit */
+                       if (y < midpoint)
+                       {
+                               if (!cave_floor_bold(y + 1, x)) return;
+                       }
+                       else if (y > midpoint)
+                       {
+                               if (!cave_floor_bold(y - 1, x)) return;
+                       }
+               }
+       }
+
+       /* We trust temp_n does not exceed TEMP_MAX */
+
+       /* New grid */
+       if (!(c_ptr->info & CAVE_MNDK))
        {
+               /* Save this square */
                temp_x[temp_n] = x;
                temp_y[temp_n] = y;
                temp_n++;
        }
 
+       /* Darkened grid */
+       else
+       {
+               /* No longer dark */
+               c_ptr->info &= ~(CAVE_MNDK);
+       }
+
        /* Light it */
        c_ptr->info |= CAVE_MNLT;
 }
 
+
+/*
+ * Add a square to the changes array
+ */
+static void mon_dark_hack(int y, int x)
+{
+       cave_type *c_ptr;
+       int       midpoint, dpf, d;
+
+       /* We trust this grid is in bounds */
+       /* if (!in_bounds2(y, x)) return; */
+
+       c_ptr = &cave[y][x];
+
+       /* Want a unlit and undarkened square in view of the player */
+       if ((c_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
+
+       if (!cave_floor_grid(c_ptr))
+       {
+               /* Hack XXX XXX - Is it a wall and monster not in LOS? */
+               if (mon_invis) return;
+
+               /* Hack -- Prevent monster dark lite leakage in walls */
+
+               /* Horizontal walls between player and a monster */
+               if (((y < py) && (y > mon_fy)) || ((y > py) && (y < mon_fy)))
+               {
+                       dpf = py - mon_fy;
+                       d = y - mon_fy;
+                       midpoint = mon_fx + ((px - mon_fx) * ABS(d)) / ABS(dpf);
+
+                       /* Only first wall viewed from mid-x is lit */
+                       if (x < midpoint)
+                       {
+                               if (!cave_floor_bold(y, x + 1)) return;
+                       }
+                       else if (x > midpoint)
+                       {
+                               if (!cave_floor_bold(y, x - 1)) return;
+                       }
+               }
+
+               /* Vertical walls between player and a monster */
+               if (((x < px) && (x > mon_fx)) || ((x > px) && (x < mon_fx)))
+               {
+                       dpf = px - mon_fx;
+                       d = x - mon_fx;
+                       midpoint = mon_fy + ((py - mon_fy) * ABS(d)) / ABS(dpf);
+
+                       /* Only first wall viewed from mid-y is lit */
+                       if (y < midpoint)
+                       {
+                               if (!cave_floor_bold(y + 1, x)) return;
+                       }
+                       else if (y > midpoint)
+                       {
+                               if (!cave_floor_bold(y - 1, x)) return;
+                       }
+               }
+       }
+
+       /* We trust temp_n does not exceed TEMP_MAX */
+
+       /* Save this square */
+       temp_x[temp_n] = x;
+       temp_y[temp_n] = y;
+       temp_n++;
+
+       /* Darken it */
+       c_ptr->info |= CAVE_MNDK;
+}
 
 
 /*
- * Update squares illuminated by monsters.
+ * Update squares illuminated or darkened by monsters.
  *
  * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
  * denote squares illuminated by monsters.
  *
- * The CAVE_TEMP flag is used to store the state during the
+ * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
  * updating.  Only squares in view of the player, whos state
  * changes are drawn via lite_spot().
  */
@@ -3123,20 +3359,25 @@ void update_mon_lite(void)
        cave_type *c_ptr;
 
        s16b fx, fy;
+       void (*add_mon_lite)(int, int);
 
        s16b end_temp;
 
+       /* Non-Ninja player in the darkness */
+       int dis_lim = ((d_info[dungeon_type].flags1 & DF1_DARKNESS) && !p_ptr->see_nocto) ?
+               (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
+
        /* Clear all monster lit squares */
        for (i = 0; i < mon_lite_n; i++)
        {
                /* Point to grid */
                c_ptr = &cave[mon_lite_y[i]][mon_lite_x[i]];
 
-               /* Set temp flag */
-               c_ptr->info |= (CAVE_TEMP);
+               /* Set temp or xtra flag */
+               c_ptr->info |= (c_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
 
                /* Clear monster illumination flag */
-               c_ptr->info &= ~(CAVE_MNLT);
+               c_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
        }
 
        /* Empty temp list of new squares to lite up */
@@ -3152,7 +3393,10 @@ void update_mon_lite(void)
                if (!m_ptr->r_idx) continue;
 
                /* Is it too far away? */
-               if (m_ptr->cdis > ((d_info[dungeon_type].flags1 & DF1_DARKNESS) ? MAX_SIGHT / 2 + 1 : MAX_SIGHT + 3)) continue;
+               if (m_ptr->cdis > dis_lim) continue;
+
+               /* If a monster stops time, break */
+               if (world_monster) break;
 
                /* Get lite radius */
                rad = 0;
@@ -3160,107 +3404,116 @@ void update_mon_lite(void)
                /* Note the radii are cumulative */
                if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
                if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
+               if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
+               if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
 
                /* Exit if has no light */
                if (!rad) continue;
-               if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (m_ptr->csleep || (!dun_level && is_daytime()) || p_ptr->inside_battle)) continue;
-
-               if (world_monster) continue;
-
-               if (d_info[dungeon_type].flags1 & DF1_DARKNESS) rad = 1;
+               else if (rad > 0)
+               {
+                       if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (m_ptr->csleep || (!dun_level && is_daytime()) || p_ptr->inside_battle)) continue;
+                       if (d_info[dungeon_type].flags1 & DF1_DARKNESS) rad = 1;
+                       add_mon_lite = mon_lite_hack;
+               }
+               else
+               {
+                       if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (m_ptr->csleep || (!dun_level && !is_daytime()))) continue;
+                       add_mon_lite = mon_dark_hack;
+                       rad = -rad; /* Use absolute value */
+               }
 
                /* Access the location */
-               fx = m_ptr->fx;
-               fy = m_ptr->fy;
+               mon_fx = m_ptr->fx;
+               mon_fy = m_ptr->fy;
 
                /* Is the monster visible? */
-               mon_invis = !(cave[fy][fx].info & CAVE_VIEW);
+               mon_invis = !(cave[mon_fy][mon_fx].info & CAVE_VIEW);
 
                /* The square it is on */
-               mon_lite_hack(fy, fx);
+               add_mon_lite(mon_fy, mon_fx);
 
                /* Adjacent squares */
-               mon_lite_hack(fy + 1, fx);
-               mon_lite_hack(fy - 1, fx);
-               mon_lite_hack(fy, fx + 1);
-               mon_lite_hack(fy, fx - 1);
-               mon_lite_hack(fy + 1, fx + 1);
-               mon_lite_hack(fy + 1, fx - 1);
-               mon_lite_hack(fy - 1, fx + 1);
-               mon_lite_hack(fy - 1, fx - 1);
+               add_mon_lite(mon_fy + 1, mon_fx);
+               add_mon_lite(mon_fy - 1, mon_fx);
+               add_mon_lite(mon_fy, mon_fx + 1);
+               add_mon_lite(mon_fy, mon_fx - 1);
+               add_mon_lite(mon_fy + 1, mon_fx + 1);
+               add_mon_lite(mon_fy + 1, mon_fx - 1);
+               add_mon_lite(mon_fy - 1, mon_fx + 1);
+               add_mon_lite(mon_fy - 1, mon_fx - 1);
 
                /* Radius 2 */
                if (rad >= 2)
                {
                        /* South of the monster */
-                       if (cave_floor_bold(fy + 1, fx))
+                       if (cave_floor_bold(mon_fy + 1, mon_fx))
                        {
-                               mon_lite_hack(fy + 2, fx + 1);
-                               mon_lite_hack(fy + 2, fx);
-                               mon_lite_hack(fy + 2, fx - 1);
+                               add_mon_lite(mon_fy + 2, mon_fx + 1);
+                               add_mon_lite(mon_fy + 2, mon_fx);
+                               add_mon_lite(mon_fy + 2, mon_fx - 1);
 
-                               c_ptr = &cave[fy + 2][fx];
+                               c_ptr = &cave[mon_fy + 2][mon_fx];
 
                                /* Radius 3 */
                                if ((rad == 3) && cave_floor_grid(c_ptr))
                                {
-                                       mon_lite_hack(fy + 3, fx + 1);
-                                       mon_lite_hack(fy + 3, fx);
-                                       mon_lite_hack(fy + 3, fx - 1);
+                                       add_mon_lite(mon_fy + 3, mon_fx + 1);
+                                       add_mon_lite(mon_fy + 3, mon_fx);
+                                       add_mon_lite(mon_fy + 3, mon_fx - 1);
                                }
                        }
 
                        /* North of the monster */
-                       if (cave_floor_bold(fy - 1, fx))
+                       if (cave_floor_bold(mon_fy - 1, mon_fx))
                        {
-                               mon_lite_hack(fy - 2, fx + 1);
-                               mon_lite_hack(fy - 2, fx);
-                               mon_lite_hack(fy - 2, fx - 1);
+                               add_mon_lite(mon_fy - 2, mon_fx + 1);
+                               add_mon_lite(mon_fy - 2, mon_fx);
+                               add_mon_lite(mon_fy - 2, mon_fx - 1);
 
-                               c_ptr = &cave[fy - 2][fx];
+                               c_ptr = &cave[mon_fy - 2][mon_fx];
 
                                /* Radius 3 */
                                if ((rad == 3) && cave_floor_grid(c_ptr))
                                {
-                                       mon_lite_hack(fy - 3, fx + 1);
-                                       mon_lite_hack(fy - 3, fx);
-                                       mon_lite_hack(fy - 3, fx - 1);
+                                       add_mon_lite(mon_fy - 3, mon_fx + 1);
+                                       add_mon_lite(mon_fy - 3, mon_fx);
+                                       add_mon_lite(mon_fy - 3, mon_fx - 1);
                                }
                        }
 
                        /* East of the monster */
-                       if (cave_floor_bold(fy, fx + 1))
+                       if (cave_floor_bold(mon_fy, mon_fx + 1))
                        {
-                               mon_lite_hack(fy + 1, fx + 2);
-                               mon_lite_hack(fy, fx + 2);
-                               mon_lite_hack(fy - 1, fx + 2);
+                               add_mon_lite(mon_fy + 1, mon_fx + 2);
+                               add_mon_lite(mon_fy, mon_fx + 2);
+                               add_mon_lite(mon_fy - 1, mon_fx + 2);
 
-                               c_ptr = &cave[fy][fx + 2];
+                               c_ptr = &cave[mon_fy][mon_fx + 2];
 
                                /* Radius 3 */
                                if ((rad == 3) && cave_floor_grid(c_ptr))
                                {
-                                       mon_lite_hack(fy + 1, fx + 3);
-                                       mon_lite_hack(fy, fx + 3);
-                                       mon_lite_hack(fy - 1, fx + 3);
+                                       add_mon_lite(mon_fy + 1, mon_fx + 3);
+                                       add_mon_lite(mon_fy, mon_fx + 3);
+                                       add_mon_lite(mon_fy - 1, mon_fx + 3);
                                }
                        }
 
                        /* West of the monster */
-                       if (cave_floor_bold(fy, fx - 1))
+                       if (cave_floor_bold(mon_fy, mon_fx - 1))
                        {
-                               mon_lite_hack(fy + 1, fx - 2);
-                               mon_lite_hack(fy, fx - 2);
-                               mon_lite_hack(fy - 1, fx - 2);
+                               add_mon_lite(mon_fy + 1, mon_fx - 2);
+                               add_mon_lite(mon_fy, mon_fx - 2);
+                               add_mon_lite(mon_fy - 1, mon_fx - 2);
 
-                               c_ptr = &cave[fy][fx - 2];
+                               c_ptr = &cave[mon_fy][mon_fx - 2];
 
                                /* Radius 3 */
                                if ((rad == 3) && cave_floor_grid(c_ptr))
                                {
-                                       mon_lite_hack(fy + 1, fx - 3);
-                                       mon_lite_hack(fy, fx - 3);
-                                       mon_lite_hack(fy - 1, fx - 3);
+                                       add_mon_lite(mon_fy + 1, mon_fx - 3);
+                                       add_mon_lite(mon_fy, mon_fx - 3);
+                                       add_mon_lite(mon_fy - 1, mon_fx - 3);
                                }
                        }
                }
@@ -3269,27 +3522,27 @@ void update_mon_lite(void)
                if (rad == 3)
                {
                        /* South-East of the monster */
-                       if (cave_floor_bold(fy + 1, fx + 1))
+                       if (cave_floor_bold(mon_fy + 1, mon_fx + 1))
                        {
-                               mon_lite_hack(fy + 2, fx + 2);
+                               add_mon_lite(mon_fy + 2, mon_fx + 2);
                        }
 
                        /* South-West of the monster */
-                       if (cave_floor_bold(fy + 1, fx - 1))
+                       if (cave_floor_bold(mon_fy + 1, mon_fx - 1))
                        {
-                               mon_lite_hack(fy + 2, fx - 2);
+                               add_mon_lite(mon_fy + 2, mon_fx - 2);
                        }
 
                        /* North-East of the monster */
-                       if (cave_floor_bold(fy - 1, fx + 1))
+                       if (cave_floor_bold(mon_fy - 1, mon_fx + 1))
                        {
-                               mon_lite_hack(fy - 2, fx + 2);
+                               add_mon_lite(mon_fy - 2, mon_fx + 2);
                        }
 
                        /* North-West of the monster */
-                       if (cave_floor_bold(fy - 1, fx - 1))
+                       if (cave_floor_bold(mon_fy - 1, mon_fx - 1))
                        {
-                               mon_lite_hack(fy - 2, fx - 2);
+                               add_mon_lite(mon_fy - 2, mon_fx - 2);
                        }
                }
        }
@@ -3305,17 +3558,30 @@ void update_mon_lite(void)
                fx = mon_lite_x[i];
                fy = mon_lite_y[i];
 
-               if (!in_bounds2(fy, fx)) continue;
+               /* We trust this grid is in bounds */
 
                /* Point to grid */
                c_ptr = &cave[fy][fx];
 
-               /* It it no longer lit? */
-               if (!(c_ptr->info & CAVE_MNLT) && player_has_los_grid(c_ptr))
+               if (c_ptr->info & CAVE_TEMP) /* Pervious lit */
                {
-                       /* It is now unlit */
-                       note_spot(fy, fx);
-                       lite_spot(fy, fx);
+                       /* It it no longer lit? */
+                       if ((c_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
+                       {
+                               /* It is now unlit */
+                               /* Add it to later visual update */
+                               cave_note_and_redraw_later(c_ptr, fy, fx);
+                       }
+               }
+               else /* Pervious darkened */
+               {
+                       /* It it no longer darken? */
+                       if ((c_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
+                       {
+                               /* It is now undarken */
+                               /* Add it to later visual update */
+                               cave_note_and_redraw_later(c_ptr, fy, fx);
+                       }
                }
 
                /* Add to end of temp array */
@@ -3328,41 +3594,57 @@ void update_mon_lite(void)
        mon_lite_n = 0;
 
        /* Copy the temp array into the lit array lighting the new squares. */
-       for (i = 0; i < temp_n; i++)
+       for (i = 0; i < end_temp; i++)
        {
                fx = temp_x[i];
                fy = temp_y[i];
 
-               if (!in_bounds2(fy, fx)) continue;
+               /* We trust this grid is in bounds */
 
                /* Point to grid */
                c_ptr = &cave[fy][fx];
 
-               if (i >= end_temp)
-               {
-                       /* Clear the temp flag for the old lit grids */
-                       c_ptr->info &= ~(CAVE_TEMP);
-               }
-               else
+               if (c_ptr->info & CAVE_MNLT) /* Lit */
                {
                        /* The is the square newly lit and visible? */
                        if ((c_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
                        {
                                /* It is now lit */
-                               lite_spot(fy, fx);
-                               note_spot(fy, fx);
+                               /* Add it to later visual update */
+                               cave_note_and_redraw_later(c_ptr, fy, fx);
                        }
-
-                       /* Save in the monster lit array */
-                       mon_lite_x[mon_lite_n] = fx;
-                       mon_lite_y[mon_lite_n] = fy;
-                       mon_lite_n++;
                }
+               else /* Darkened */
+               {
+                       /* The is the square newly darkened and visible? */
+                       if ((c_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
+                       {
+                               /* It is now darkened */
+                               /* Add it to later visual update */
+                               cave_note_and_redraw_later(c_ptr, fy, fx);
+                       }
+               }
+
+               /* Save in the monster lit or darkened array */
+               mon_lite_x[mon_lite_n] = fx;
+               mon_lite_y[mon_lite_n] = fy;
+               mon_lite_n++;
+       }
+
+       /* Clear the temp flag for the old lit or darken grids */
+       for (i = end_temp; i < temp_n; i++)
+       {
+               /* We trust this grid is in bounds */
+
+               cave[temp_y[i]][temp_x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
        }
 
        /* Finished with temp_n */
        temp_n = 0;
 
+       /* Mega-Hack -- Visual update later */
+       p_ptr->update |= (PU_DELAY_VIS);
+
        p_ptr->monlite = (cave[py][px].info & CAVE_MNLT) ? TRUE : FALSE;
 
        if (p_ptr->special_defense & NINJA_S_STEALTH)
@@ -3402,7 +3684,7 @@ void clear_mon_lite(void)
                c_ptr = &cave[mon_lite_y[i]][mon_lite_x[i]];
 
                /* Clear monster illumination flag */
-               c_ptr->info &= ~(CAVE_MNLT);
+               c_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
        }
 
        /* Empty the array */
@@ -4093,11 +4375,8 @@ void update_view(void)
                /* Update only newly viewed grids */
                if (c_ptr->info & (CAVE_TEMP)) continue;
 
-               /* Note */
-               note_spot(y, x);
-
-               /* Redraw */
-               lite_spot(y, x);
+               /* Add it to later visual update */
+               cave_note_and_redraw_later(c_ptr, y, x);
        }
 
        /* Wipe the old grids, update as needed */
@@ -4115,15 +4394,56 @@ void update_view(void)
                /* Update only non-viewable grids */
                if (c_ptr->info & (CAVE_VIEW)) continue;
 
-               /* Redraw */
-               lite_spot(y, x);
+               /* Add it to later visual update */
+               cave_redraw_later(c_ptr, y, x);
        }
 
        /* None left */
        temp_n = 0;
+
+       /* Mega-Hack -- Visual update later */
+       p_ptr->update |= (PU_DELAY_VIS);
 }
 
 
+/*
+ * Mega-Hack -- Delayed visual update
+ * Only used if update_view(), update_lite() or update_mon_lite() was called
+ */
+void delayed_visual_update(void)
+{
+       int       i, y, x;
+       cave_type *c_ptr;
+
+       /* Update needed grids */
+       for (i = 0; i < redraw_n; i++)
+       {
+               y = redraw_y[i];
+               x = redraw_x[i];
+
+               /* Access the grid */
+               c_ptr = &cave[y][x];
+
+               /* Update only needed grids (prevent multiple updating) */
+               if (!(c_ptr->info & CAVE_REDRAW)) continue;
+
+               /* If required, note */
+               if (c_ptr->info & CAVE_NOTE) note_spot(y, x);
+
+               /* Redraw */
+               lite_spot(y, x);
+
+               /* Hack -- Visual update of monster on this grid */
+               if (c_ptr->m_idx) update_mon(c_ptr->m_idx, FALSE);
+
+               /* No longer in the array */
+               c_ptr->info &= ~(CAVE_NOTE | CAVE_REDRAW);
+       }
+
+       /* None left */
+       redraw_n = 0;
+}
+
 
 /*
  * Hack -- forget the "flow" information
@@ -4228,10 +4548,10 @@ void update_flow(void)
                        x = tx + ddx_ddd[d];
 
                        /* Ignore player's grid */
-                       if (x == px && y == py) continue;
+                       if (player_bold(y, x)) continue;
 
                        c_ptr = &cave[y][x];
-                                      
+
                        if (is_closed_door(c_ptr->feat)) m += 3;
 
                        /* Ignore "pre-stamped" entries */
@@ -4555,7 +4875,7 @@ void wiz_dark(void)
        p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
 
        /* Update the view and lite */
-       p_ptr->update |= (PU_VIEW | PU_LITE);
+       p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
 
        /* Update the monsters */
        p_ptr->update |= (PU_MONSTERS);
@@ -4903,9 +5223,9 @@ void disturb(int stop_search, int unused_flag)
 
 
 /*
- * Glow deep lava in the floor
+ * Glow deep lava and building entrances in the floor
  */
-void glow_deep_lava(void)
+void glow_deep_lava_and_bldg(void)
 {
        int y, x, i, yy, xx;
        cave_type *c_ptr;
@@ -4923,7 +5243,12 @@ void glow_deep_lava(void)
                        /* Feature code (applying "mimic" field) */
                        feat = c_ptr->mimic ? c_ptr->mimic : f_info[c_ptr->feat].mimic;
 
-                       if (feat == FEAT_DEEP_LAVA)
+                       if ((feat == FEAT_DEEP_LAVA) ||
+                          ((feat >= FEAT_SHOP_HEAD) &&
+                           (feat <= FEAT_SHOP_TAIL)) ||
+                           (feat == FEAT_MUSEUM) ||
+                          ((feat >= FEAT_BLDG_HEAD) &&
+                           (feat <= FEAT_BLDG_TAIL)))
                        {
                                for (i = 0; i < 9; i++)
                                {