Guest User

NetHack guiding candle patch

a guest
Sep 2nd, 2019
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 64.73 KB | None | 0 0
  1. diff --git c/include/display.h w/include/display.h
  2. index 9da288d..4a1d63b 100644
  3. --- c/include/display.h
  4. +++ w/include/display.h
  5. @@ -59,9 +59,9 @@
  6.   * Infravision is not taken into account.
  7.   */
  8.  #define mon_visible(mon) \
  9. -    (/* The hero can see the monster IF the monster                     */ \
  10. -     (!mon->minvis || See_invisible)  /*     1. is not invisible        */ \
  11. -     && !mon->mundetected             /* AND 2. not an undetected hider */ \
  12. +    (/* The hero can see the monster IF the monster                        */ \
  13. +     (!minvisible(mon) || See_invisible) /*     1. is not invisible        */ \
  14. +     && !mon->mundetected                /* AND 2. not an undetected hider */ \
  15.       && !(mon->mburied || u.uburied)) /* AND 3. neither you nor it is buried */
  16.  
  17.  /*
  18. @@ -110,7 +110,8 @@
  19.   */
  20.  #define knowninvisible(mon)                                               \
  21.      (mtmp->minvis                                                         \
  22. -     && ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) \
  23. +     && ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters   \
  24. +                                       || candetect(mon->mx, mon->my)))   \
  25.           || (!Blind && (HTelepat & ~INTRINSIC)                            \
  26.               && distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM))))
  27.  
  28. diff --git c/include/extern.h w/include/extern.h
  29. index 6959e24..36e7776 100644
  30. --- c/include/extern.h
  31. +++ w/include/extern.h
  32. @@ -275,6 +275,7 @@ E void FDECL(use_crystal_ball, (struct obj **));
  33.  E void NDECL(do_mapping);
  34.  E void FDECL(do_vicinity_map, (struct obj *));
  35.  E void FDECL(cvt_sdoor_to_door, (struct rm *));
  36. +E boolean FDECL(findone_core, (int, int));
  37.  #ifdef USE_TRAMPOLI
  38.  E void FDECL(findone, (int, int, genericptr_t));
  39.  E void FDECL(openone, (int, int, genericptr_t));
  40. @@ -1064,7 +1065,7 @@ E void FDECL(obj_split_light_source, (struct obj *, struct obj *));
  41.  E void FDECL(obj_merge_light_sources, (struct obj *, struct obj *));
  42.  E void FDECL(obj_adjust_light_radius, (struct obj *, int));
  43.  E int FDECL(candle_light_range, (struct obj *));
  44. -E int FDECL(arti_light_radius, (struct obj *));
  45. +E int FDECL(dynamic_light_radius, (struct obj *));
  46.  E const char *FDECL(arti_light_description, (struct obj *));
  47.  E int NDECL(wiz_light_sources);
  48.  
  49. @@ -1418,6 +1419,7 @@ E void FDECL(setmangry, (struct monst *, BOOLEAN_P));
  50.  E void FDECL(wakeup, (struct monst *, BOOLEAN_P));
  51.  E void NDECL(wake_nearby);
  52.  E void FDECL(wake_nearto, (int, int, int));
  53. +E void FDECL(seemimic_noredraw, (struct monst *));
  54.  E void FDECL(seemimic, (struct monst *));
  55.  E void NDECL(rescham);
  56.  E void NDECL(restartcham);
  57. diff --git c/include/mkroom.h w/include/mkroom.h
  58. index 9d72455..df6a0f7 100644
  59. --- c/include/mkroom.h
  60. +++ w/include/mkroom.h
  61. @@ -34,7 +34,7 @@ struct shclass {
  62.      struct itp {
  63.          int iprob; /* probability of an item type */
  64.          int itype; /* item type: if >=0 a class, if < 0 a specific item */
  65. -    } iprobs[6];
  66. +    } iprobs[7];
  67.      const char *const *shknms; /* list of shopkeeper names for this type */
  68.  };
  69.  
  70. diff --git c/include/mondata.h w/include/mondata.h
  71. index 41b5f70..f96d574 100644
  72. --- c/include/mondata.h
  73. +++ w/include/mondata.h
  74. @@ -75,6 +75,7 @@
  75.      (lays_eggs(ptr) && (ptr)->mlet == S_EEL && is_swimmer(ptr))
  76.  #define regenerates(ptr) (((ptr)->mflags1 & M1_REGEN) != 0L)
  77.  #define perceives(ptr) (((ptr)->mflags1 & M1_SEE_INVIS) != 0L)
  78. +#define perceives_you(ptr) (perceives(ptr) || candetect(u.ux, u.uy))
  79.  #define can_teleport(ptr) (((ptr)->mflags1 & M1_TPORT) != 0L)
  80.  #define control_teleport(ptr) (((ptr)->mflags1 & M1_TPORT_CNTRL) != 0L)
  81.  #define telepathic(ptr)                                                \
  82. diff --git c/include/monst.h w/include/monst.h
  83. index f9be37f..4882176 100644
  84. --- c/include/monst.h
  85. +++ w/include/monst.h
  86. @@ -174,6 +174,9 @@ struct monst {
  87.      ((mon)->cham == PM_VAMPIRE || (mon)->cham == PM_VAMPIRE_LORD \
  88.       || (mon)->cham == PM_VLAD_THE_IMPALER)
  89.  
  90. +/* guiding candle makes monsters effectively visible */
  91. +#define minvisible(mon) ((mon)->minvis && !candetect((mon)->mx, (mon)->my))
  92. +
  93.  /* mimic appearances that block vision/light */
  94.  #define is_lightblocker_mappear(mon)                       \
  95.      (is_obj_mappear(mon, BOULDER)                          \
  96. diff --git c/include/obj.h w/include/obj.h
  97. index 62e20b7..6796141 100644
  98. --- c/include/obj.h
  99. +++ w/include/obj.h
  100. @@ -302,7 +302,9 @@ struct obj {
  101.  
  102.  /* Light sources */
  103.  #define Is_candle(otmp) \
  104. -    (otmp->otyp == TALLOW_CANDLE || otmp->otyp == WAX_CANDLE)
  105. +    (otmp->otyp == TALLOW_CANDLE || otmp->otyp == WAX_CANDLE \
  106. +     || otmp->otyp == GUIDING_CANDLE)
  107. +#define candle_burn_time(otmp) ((otmp)->otyp == TALLOW_CANDLE ? 200L : 400L)
  108.  #define MAX_OIL_IN_FLASK 400 /* maximum amount of oil in a potion of oil */
  109.  
  110.  /* MAGIC_LAMP intentionally excluded below */
  111. diff --git c/include/rm.h w/include/rm.h
  112. index d6ec078..07676fe 100644
  113. --- c/include/rm.h
  114. +++ w/include/rm.h
  115. @@ -388,6 +388,16 @@ extern struct symsetentry symset[NUM_GRAPHICS]; /* from drawing.c */
  116.  #define W_NONDIGGABLE 0x08
  117.  #define W_NONPASSWALL 0x10
  118.  
  119. +/*
  120. + * Filled trapdoors in the Castle can be dug out again.
  121. + * Conflicts with W_NONPASSWALL above, but Castle has no
  122. + * non-passwall walls anyway, much less those that can be dug.
  123. + */
  124. +
  125. +#define FL_DIGGABLE 0x10
  126. +#define Can_dig_hole(x,y,z) (Can_dig_down(z) || Can_fall_thru(z)             \
  127. +                             && (level.locations[x][y].flags & FL_DIGGABLE))
  128. +
  129.  /*
  130.   * Ladders (in Vlad's tower) may be up or down.
  131.   */
  132. @@ -419,7 +429,7 @@ struct rm {
  133.  
  134.      Bitfield(roomno, 6); /* room # for special rooms */
  135.      Bitfield(edge, 1);   /* marks boundaries for special rooms*/
  136. -    Bitfield(candig, 1); /* Exception to Can_dig_down; was a trapdoor */
  137. +    Bitfield(buried, 1); /* true iff there are buried objects here */
  138.  };
  139.  
  140.  #define SET_TYPLIT(x, y, ttyp, llit)                              \
  141. diff --git c/include/vision.h w/include/vision.h
  142. index 562f542..5cb5aec 100644
  143. --- c/include/vision.h
  144. +++ w/include/vision.h
  145. @@ -11,15 +11,17 @@ extern char **viz_array;        /* could see/in sight row pointers */
  146.  extern char *viz_rmin;         /* min could see indices */
  147.  extern char *viz_rmax;         /* max could see indices */
  148.  #endif
  149. -#define COULD_SEE 0x1 /* location could be seen, if it were lit */
  150. -#define IN_SIGHT 0x2  /* location can be seen */
  151. -#define TEMP_LIT 0x4  /* location is temporarily lit */
  152. +#define COULD_SEE 0x1   /* location could be seen, if it were lit */
  153. +#define IN_SIGHT 0x2    /* location can be seen */
  154. +#define TEMP_LIT 0x4    /* location is temporarily lit */
  155. +#define TEMP_DETECT 0x8 /* lit by a guiding candle */
  156.  
  157.  /*
  158.   * Light source sources
  159.   */
  160.  #define LS_OBJECT 0
  161.  #define LS_MONSTER 1
  162. +#define LS_DETECT 2  /* guiding candle */
  163.  
  164.  /*
  165.   *  cansee()   - Returns true if the hero can see the location.
  166. @@ -30,6 +32,7 @@ extern char *viz_rmax;            /* max could see indices */
  167.  #define cansee(x, y) (viz_array[y][x] & IN_SIGHT)
  168.  #define couldsee(x, y) (viz_array[y][x] & COULD_SEE)
  169.  #define templit(x, y) (viz_array[y][x] & TEMP_LIT)
  170. +#define candetect(x, y) (viz_array[y][x] & TEMP_DETECT)
  171.  
  172.  /*
  173.   *  The following assume the monster is not blind.
  174. @@ -44,7 +47,7 @@ extern char *viz_rmax;            /* max could see indices */
  175.  #define m_cansee(mtmp, x2, y2) clear_path((mtmp)->mx, (mtmp)->my, (x2), (y2))
  176.  
  177.  #define m_canseeu(m)                                       \
  178. -    ((!Invis || perceives((m)->data))                      \
  179. +    ((!Invis || perceives_you((m)->data))                  \
  180.               && !(Underwater || u.uburied || (m)->mburied) \
  181.           ? couldsee((m)->mx, (m)->my)                      \
  182.           : 0)
  183. diff --git c/include/youprop.h w/include/youprop.h
  184. index c0eb10e..32b75ae 100644
  185. --- c/include/youprop.h
  186. +++ w/include/youprop.h
  187. @@ -177,7 +177,7 @@
  188.  #define EInvis u.uprops[INVIS].extrinsic
  189.  #define BInvis u.uprops[INVIS].blocked
  190.  #define Invis ((HInvis || EInvis) && !BInvis)
  191. -#define Invisible (Invis && !See_invisible)
  192. +#define Invisible (Invis && !See_invisible && !candetect(u.ux, u.uy))
  193.  /* Note: invisibility also hides inventory and steed */
  194.  
  195.  #define EDisplaced u.uprops[DISPLACED].extrinsic
  196. diff --git c/src/apply.c w/src/apply.c
  197. index 998d4dd..541ccd6 100644
  198. --- c/src/apply.c
  199. +++ w/src/apply.c
  200. @@ -816,11 +816,11 @@ struct obj *obj;
  201.      struct monst *mtmp;
  202.      unsigned how_seen;
  203.      char mlet;
  204. -    boolean vis, invis_mirror, useeit, monable;
  205. +    boolean vis, invis_mirror, useeit, mcanseeself, monable;
  206.  
  207.      if (!getdir((char *) 0))
  208.          return 0;
  209. -    invis_mirror = Invis;
  210. +    invis_mirror = Invis && !candetect(u.ux, u.uy);
  211.      useeit = !Blind && (!invis_mirror || See_invisible);
  212.      uvisage = beautiful();
  213.      mirror = simpleonames(obj); /* "mirror" or "looking glass" */
  214. @@ -895,7 +895,7 @@ struct obj *obj;
  215.  #define SEENMON (MONSEEN_NORMAL | MONSEEN_SEEINVIS | MONSEEN_INFRAVIS)
  216.      how_seen = vis ? howmonseen(mtmp) : 0;
  217.      /* whether monster is able to use its vision-based capabilities */
  218. -    monable = !mtmp->mcan && (!mtmp->minvis || perceives(mtmp->data));
  219. +    monable = !mtmp->mcan && (!minvisible(mtmp) || perceives(mtmp->data));
  220.      mlet = mtmp->data->mlet;
  221.      if (mtmp->msleeping) {
  222.          if (vis)
  223. @@ -952,7 +952,7 @@ struct obj *obj;
  224.          if (!tele_restrict(mtmp))
  225.              (void) rloc(mtmp, TRUE);
  226.      } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data)
  227. -               && (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
  228. +               && (!minvisible(mtmp) || perceives(mtmp->data)) && rn2(5)) {
  229.          boolean do_react = TRUE;
  230.  
  231.          if (mtmp->mfrozen) {
  232. @@ -968,9 +968,9 @@ struct obj *obj;
  233.              monflee(mtmp, d(2, 4), FALSE, FALSE);
  234.          }
  235.      } else if (!Blind) {
  236. -        if (mtmp->minvis && !See_invisible)
  237. +        if (minvisible(mtmp) && !See_invisible)
  238.              ;
  239. -        else if ((mtmp->minvis && !perceives(mtmp->data))
  240. +        else if ((minvisible(mtmp) && !perceives(mtmp->data))
  241.                   /* redundant: can't get here if these are true */
  242.                   || !haseyes(mtmp->data) || notonhead || !mtmp->mcansee)
  243.              pline("%s doesn't seem to notice %s reflection.", Monnam(mtmp),
  244. @@ -1208,6 +1208,9 @@ struct obj **optr;
  245.              *optr = 0;
  246.          You("attach %ld%s %s to %s.", obj->quan, !otmp->spe ? "" : " more", s,
  247.              the(xname(otmp)));
  248. +        if (objects[obj->otyp].oc_magic) /* hello SLASH'EM */
  249. +            pline("%s very ordinary.", (obj->quan > 1L) ? "They look"
  250. +                                                        : "It looks");
  251.          if (!otmp->spe || otmp->age > obj->age)
  252.              otmp->age = obj->age;
  253.          otmp->spe += (int) obj->quan;
  254. @@ -1365,7 +1368,7 @@ struct obj *obj;
  255.              pline("%s flame%s %s%s", s_suffix(Yname2(obj)), plur(obj->quan),
  256.                    otense(obj, "burn"), Blind ? "." : " brightly!");
  257.              if (obj->unpaid && costly_spot(u.ux, u.uy)
  258. -                && obj->age == 20L * (long) objects[obj->otyp].oc_cost) {
  259. +                && obj->age == candle_burn_time(obj)) {
  260.                  const char *ithem = (obj->quan > 1L) ? "them" : "it";
  261.  
  262.                  verbalize("You burn %s, you bought %s!", ithem, ithem);
  263. @@ -2107,7 +2110,7 @@ long timeout;
  264.          /* [m_monnam() yields accurate mon type, overriding hallucination] */
  265.          Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
  266.          and_vanish[0] = '\0';
  267. -        if ((mtmp->minvis && !See_invisible)
  268. +        if ((minvisible(mtmp) && !See_invisible)
  269.              || (mtmp->data->mlet == S_MIMIC
  270.                  && M_AP_TYPE(mtmp) != M_AP_NOTHING))
  271.              suppress_see = TRUE;
  272. @@ -3402,8 +3405,7 @@ struct obj *obj;
  273.                      fillmsg = TRUE;
  274.                  } else
  275.                      digactualhole(x, y, BY_OBJECT, (rn2(obj->spe) < 3
  276. -                                                    || (!Can_dig_down(&u.uz)
  277. -                                                        && !levl[x][y].candig))
  278. +                                                 || !Can_dig_hole(x, y, &u.uz))
  279.                                                        ? PIT
  280.                                                        : HOLE);
  281.              }
  282. @@ -3652,6 +3654,7 @@ doapply()
  283.          break;
  284.      case WAX_CANDLE:
  285.      case TALLOW_CANDLE:
  286. +    case GUIDING_CANDLE:
  287.          use_candle(&obj);
  288.          break;
  289.      case OIL_LAMP:
  290. diff --git c/src/detect.c w/src/detect.c
  291. index 4527168..c2a4803 100644
  292. --- c/src/detect.c
  293. +++ w/src/detect.c
  294. @@ -1443,46 +1443,59 @@ struct rm *lev;
  295.      lev->doormask = newmask;
  296.  }
  297.  
  298. -STATIC_PTR void
  299. -findone(zx, zy, num)
  300. +/* also used in display.c */
  301. +boolean
  302. +findone_core(zx, zy)
  303.  int zx, zy;
  304. -genericptr_t num;
  305.  {
  306.      register struct trap *ttmp;
  307.      register struct monst *mtmp;
  308. +    boolean result = FALSE;
  309.  
  310.      if (levl[zx][zy].typ == SDOOR) {
  311.          cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
  312.          magic_map_background(zx, zy, 0);
  313. -        newsym(zx, zy);
  314. -        (*(int *) num)++;
  315. -    } else if (levl[zx][zy].typ == SCORR) {
  316. +        return TRUE;
  317. +    }
  318. +    if (levl[zx][zy].typ == SCORR) {
  319.          levl[zx][zy].typ = CORR;
  320.          unblock_point(zx, zy);
  321.          magic_map_background(zx, zy, 0);
  322. -        newsym(zx, zy);
  323. -        (*(int *) num)++;
  324. -    } else if ((ttmp = t_at(zx, zy)) != 0) {
  325. +        return TRUE;
  326. +    }
  327. +    if ((ttmp = t_at(zx, zy)) != 0) {
  328.          if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
  329.              ttmp->tseen = 1;
  330. -            newsym(zx, zy);
  331. -            (*(int *) num)++;
  332. +            return TRUE;
  333.          }
  334. -    } else if ((mtmp = m_at(zx, zy)) != 0) {
  335. +    }
  336. +    if ((mtmp = m_at(zx, zy)) != 0) {
  337.          if (M_AP_TYPE(mtmp)) {
  338. -            seemimic(mtmp);
  339. -            (*(int *) num)++;
  340. +            seemimic_noredraw(mtmp);
  341. +            result = TRUE;
  342.          }
  343.          if (mtmp->mundetected
  344.              && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) {
  345.              mtmp->mundetected = 0;
  346. -            newsym(zx, zy);
  347. -            (*(int *) num)++;
  348. +            result = TRUE;
  349.          }
  350.          if (!canspotmon(mtmp) && !glyph_is_invisible(levl[zx][zy].glyph))
  351.              map_invisible(zx, zy);
  352. -    } else if (unmap_invisible(zx, zy)) {
  353. +    } else if (glyph_is_invisible(levl[zx][zy].glyph)) {
  354. +        unmap_object(zx, zy);
  355. +        result = TRUE;
  356. +    }
  357. +    return result;
  358. +}
  359. +
  360. +STATIC_PTR void
  361. +findone(zx, zy, num)
  362. +int zx, zy;
  363. +genericptr_t num;
  364. +{
  365. +    if (findone_core(zx, zy)) {
  366.          (*(int *) num)++;
  367. +        newsym(zx, zy);
  368.      }
  369.  }
  370.  
  371. diff --git c/src/dig.c w/src/dig.c
  372. index dbf5eb5..d44ea1f 100644
  373. --- c/src/dig.c
  374. +++ w/src/dig.c
  375. @@ -219,7 +219,7 @@ int x, y;
  376.                 || (ttmp
  377.                     && (ttmp->ttyp == MAGIC_PORTAL
  378.                         || ttmp->ttyp == VIBRATING_SQUARE
  379. -                       || (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) {
  380. +                       || !Can_dig_hole(x, y, &u.uz)))) {
  381.          if (verbose)
  382.              pline_The("%s here is too hard to %s.", surface(x, y), verb);
  383.          return FALSE;
  384. @@ -579,7 +579,7 @@ int ttyp;
  385.          return;
  386.      }
  387.  
  388. -    if (ttyp != PIT && (!Can_dig_down(&u.uz) && !lev->candig)) {
  389. +    if (ttyp != PIT && !Can_dig_hole(x, y, &u.uz)) {
  390.          impossible("digactualhole: can't dig %s on this level.",
  391.                     defsyms[trap_to_defsym(ttyp)].explanation);
  392.          ttyp = PIT;
  393. @@ -783,7 +783,7 @@ coord *cc;
  394.  
  395.      ttmp = t_at(dig_x, dig_y);
  396.      lev = &levl[dig_x][dig_y];
  397. -    nohole = (!Can_dig_down(&u.uz) && !lev->candig);
  398. +    nohole = !Can_dig_hole(dig_x, dig_y, &u.uz);
  399.  
  400.      if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL
  401.                    || ttmp->ttyp == VIBRATING_SQUARE || nohole))
  402. @@ -866,9 +866,9 @@ coord *cc;
  403.      } else {
  404.          typ = fillholetyp(dig_x, dig_y, FALSE);
  405.  
  406. -        lev->flags = 0;
  407.          if (typ != ROOM) {
  408.              lev->typ = typ;
  409. +            lev->flags = 0;
  410.              liquid_flow(dig_x, dig_y, typ, ttmp,
  411.                          "As you dig, the hole fills with %s!");
  412.              return TRUE;
  413. @@ -1931,23 +1931,27 @@ int x, y;
  414.      coord cc;
  415.  
  416.      debugpline2("unearth_objs: at <%d,%d>", x, y);
  417. -    cc.x = x;
  418. -    cc.y = y;
  419. -    bball = buried_ball(&cc);
  420. -    for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
  421. -        otmp2 = otmp->nobj;
  422. -        if (otmp->ox == x && otmp->oy == y) {
  423. -            if (bball && otmp == bball
  424. -                && u.utrap && u.utraptype == TT_BURIEDBALL) {
  425. -                buried_ball_to_punishment();
  426. -            } else {
  427. -                obj_extract_self(otmp);
  428. -                if (otmp->timed)
  429. -                    (void) stop_timer(ROT_ORGANIC, obj_to_any(otmp));
  430. -                place_object(otmp, x, y);
  431. -                stackobj(otmp);
  432. +
  433. +    if (levl[x][y].buried) {
  434. +        cc.x = x;
  435. +        cc.y = y;
  436. +        bball = buried_ball(&cc);
  437. +        for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
  438. +            otmp2 = otmp->nobj;
  439. +            if (otmp->ox == x && otmp->oy == y) {
  440. +                if (bball && otmp == bball
  441. +                    && u.utrap && u.utraptype == TT_BURIEDBALL) {
  442. +                    buried_ball_to_punishment();
  443. +                } else {
  444. +                    obj_extract_self(otmp);
  445. +                    if (otmp->timed)
  446. +                        (void) stop_timer(ROT_ORGANIC, obj_to_any(otmp));
  447. +                    place_object(otmp, x, y);
  448. +                    stackobj(otmp);
  449. +                }
  450.              }
  451.          }
  452. +        levl[x][y].buried = 0;
  453.      }
  454.      del_engr_at(x, y);
  455.      newsym(x, y);
  456. diff --git c/src/display.c w/src/display.c
  457. index c5b155b..2ea8b06 100644
  458. --- c/src/display.c
  459. +++ w/src/display.c
  460. @@ -123,6 +123,7 @@
  461.   */
  462.  #include "hack.h"
  463.  
  464. +STATIC_DCL void FDECL(map_buried, (int, int, int));
  465.  STATIC_DCL void FDECL(display_monster,
  466.                        (XCHAR_P, XCHAR_P, struct monst *, int, XCHAR_P));
  467.  STATIC_DCL int FDECL(swallow_to_glyph, (int, int));
  468. @@ -264,6 +265,26 @@ register int show;
  469.          show_glyph(x, y, glyph);
  470.  }
  471.  
  472. +/*
  473. + * map_buried()
  474. + * Map the object buried under the specified tile.
  475. + * If there are several, we need to display the very last one
  476. + * to be consistent with object_detect().
  477. + */
  478. +
  479. +STATIC_OVL void
  480. +map_buried(x, y, show)
  481. +int x, y;
  482. +int show;
  483. +{
  484. +    struct obj *obj, *last_obj = NULL;
  485. +    for (obj = level.buriedobjlist; obj; obj = obj->nobj)
  486. +        if (obj->ox == x && obj->oy == y)
  487. +            last_obj = obj;
  488. +    if (last_obj)
  489. +        map_object(last_obj, show);
  490. +}
  491. +
  492.  /*
  493.   * map_invisible()
  494.   *
  495. @@ -344,8 +365,11 @@ register int x, y;
  496.          register struct obj *obj;                                           \
  497.          register struct trap *trap;                                         \
  498.                                                                              \
  499. -        if ((obj = vobj_at(x, y)) && !covers_objects(x, y))                 \
  500. +        if ((obj = vobj_at(x, y)) && (!covers_objects(x, y)                 \
  501. +                                      || candetect(x, y) && cansee(x, y)))  \
  502.              map_object(obj, show);                                          \
  503. +        else if (levl[x][y].buried && candetect(x, y) && cansee(x, y))      \
  504. +            map_buried(x, y, show);                                         \
  505.          else if ((trap = t_at(x, y)) && trap->tseen && !covers_traps(x, y)) \
  506.              map_trap(trap, show);                                           \
  507.          else                                                                \
  508. @@ -772,6 +796,10 @@ register int x, y;
  509.              return;
  510.          }
  511.  
  512. +        /* guiding candle! */
  513. +        if (candetect(x,y))
  514. +            findone_core(x,y);
  515. +
  516.          if (x == u.ux && y == u.uy) {
  517.              int see_self = canspotself();
  518.  
  519. diff --git c/src/do_name.c w/src/do_name.c
  520. index 6dd8d5a..48921b0 100644
  521. --- c/src/do_name.c
  522. +++ w/src/do_name.c
  523. @@ -1151,7 +1151,7 @@ do_mname()
  524.              && (!(cansee(cx, cy) || see_with_infrared(mtmp))
  525.                  || mtmp->mundetected || M_AP_TYPE(mtmp) == M_AP_FURNITURE
  526.                  || M_AP_TYPE(mtmp) == M_AP_OBJECT
  527. -                || (mtmp->minvis && !See_invisible)))) {
  528. +                || (minvisible(mtmp) && !See_invisible)))) {
  529.          pline("I see no monster there.");
  530.          return;
  531.      }
  532. diff --git c/src/do_wear.c w/src/do_wear.c
  533. index 9132e75..df2de3f 100644
  534. --- c/src/do_wear.c
  535. +++ w/src/do_wear.c
  536. @@ -287,8 +287,9 @@ Cloak_on(VOID_ARGS)
  537.          /* Note: it's already being worn, so we have to cheat here. */
  538.          if ((HInvis || EInvis) && !Blind) {
  539.              newsym(u.ux, u.uy);
  540. -            You("can %s!", See_invisible ? "no longer see through yourself"
  541. -                                         : see_yourself);
  542. +            You("can %s!", See_invisible || candetect(u.ux, u.uy)
  543. +                           ? "no longer see through yourself"
  544. +                           : see_yourself);
  545.          }
  546.          break;
  547.      case CLOAK_OF_INVISIBILITY:
  548. @@ -298,7 +299,7 @@ Cloak_on(VOID_ARGS)
  549.              makeknown(uarmc->otyp);
  550.              newsym(u.ux, u.uy);
  551.              pline("Suddenly you can%s yourself.",
  552. -                  See_invisible ? " see through" : "not see");
  553. +                  !Invisible ? " see through" : "not see");
  554.          }
  555.          break;
  556.      case OILSKIN_CLOAK:
  557. @@ -343,8 +344,8 @@ Cloak_off(VOID_ARGS)
  558.      case MUMMY_WRAPPING:
  559.          if (Invis && !Blind) {
  560.              newsym(u.ux, u.uy);
  561. -            You("can %s.", See_invisible ? "see through yourself"
  562. -                                         : "no longer see yourself");
  563. +            You("can %s.", !Invisible ? "see through yourself"
  564. +                                      : "no longer see yourself");
  565.          }
  566.          break;
  567.      case CLOAK_OF_INVISIBILITY:
  568. @@ -352,8 +353,9 @@ Cloak_off(VOID_ARGS)
  569.              makeknown(CLOAK_OF_INVISIBILITY);
  570.              newsym(u.ux, u.uy);
  571.              pline("Suddenly you can %s.",
  572. -                  See_invisible ? "no longer see through yourself"
  573. -                                : see_yourself);
  574. +                  See_invisible || candetect(u.ux, u.uy)
  575. +                  ? "no longer see through yourself"
  576. +                  : see_yourself);
  577.          }
  578.          break;
  579.      /* Alchemy smock gives poison _and_ acid resistance */
  580. @@ -900,7 +902,8 @@ register struct obj *obj;
  581.          set_mimic_blocking(); /* do special mimic handling */
  582.          see_monsters();
  583.  
  584. -        if (Invis && !oldprop && !HSee_invisible && !Blind) {
  585. +        if (Invis && !oldprop && !HSee_invisible
  586. +            && !Blind && !candetect(u.ux, u.uy)) {
  587.              newsym(u.ux, u.uy);
  588.              pline("Suddenly you are transparent, but there!");
  589.              learnring(obj, TRUE);
  590. @@ -1024,7 +1027,8 @@ boolean gone;
  591.          if (!Invis && !BInvis && !Blind) {
  592.              newsym(u.ux, u.uy);
  593.              Your("body seems to unfade%s.",
  594. -                 See_invisible ? " completely" : "..");
  595. +                 See_invisible || candetect(u.ux, u.uy) ? " completely"
  596. +                                                        : "..");
  597.              learnring(obj, TRUE);
  598.          }
  599.          break;
  600. diff --git c/src/dogmove.c w/src/dogmove.c
  601. index df3452f..d3e55aa 100644
  602. --- c/src/dogmove.c
  603. +++ w/src/dogmove.c
  604. @@ -649,7 +649,7 @@ int maxdist;
  605.  
  606.          if ((targ = m_at(curx, cury)) != 0) {
  607.              /* Is the monster visible to the pet? */
  608. -            if ((!targ->minvis || perceives(mtmp->data))
  609. +            if ((!minvisible(targ) || perceives(mtmp->data))
  610.                  && !targ->mundetected)
  611.                  break;
  612.              /* If the pet can't see it, it assumes it aint there */
  613. @@ -692,7 +692,7 @@ int    maxdist;
  614.          if (pal) {
  615.              if (pal->mtame) {
  616.                  /* Pet won't notice invisible pets */
  617. -                if (!pal->minvis || perceives(mtmp->data))
  618. +                if (!minvisible(pal) || perceives(mtmp->data))
  619.                      return 1;
  620.              } else {
  621.                  /* Quest leaders and guardians are always seen */
  622. @@ -1007,7 +1007,7 @@ int after; /* this is extra fast monster movement */
  623.              if ((int) mtmp2->m_lev >= (int) mtmp->m_lev + 2
  624.                  || (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10)
  625.                      && mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
  626. -                    && (perceives(mtmp->data) || !mtmp2->minvis))
  627. +                    && (perceives(mtmp->data) || !minvisible(mtmp2)))
  628.                  || (mtmp2->data == &mons[PM_GELATINOUS_CUBE] && rn2(10))
  629.                  || (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp)
  630.                  || ((mtmp->mhp * 4 < mtmp->mhpmax
  631. diff --git c/src/eat.c w/src/eat.c
  632. index 4dd3a0a..f3bd5d0 100644
  633. --- c/src/eat.c
  634. +++ w/src/eat.c
  635. @@ -1969,15 +1969,14 @@ struct obj *otmp;
  636.                  set_mimic_blocking();
  637.                  see_monsters();
  638.                  if (Invis && !oldprop && !ESee_invisible
  639. -                    && !perceives(youmonst.data) && !Blind) {
  640. +                    && !perceives_you(youmonst.data) && !Blind) {
  641.                      newsym(u.ux, u.uy);
  642.                      pline("Suddenly you can see yourself.");
  643.                      makeknown(typ);
  644.                  }
  645.                  break;
  646.              case RIN_INVISIBILITY:
  647. -                if (!oldprop && !EInvis && !BInvis && !See_invisible
  648. -                    && !Blind) {
  649. +                if (!oldprop && !EInvis && !BInvis && Invisible && !Blind) {
  650.                      newsym(u.ux, u.uy);
  651.                      Your("body takes on a %s transparency...",
  652.                           Hallucination ? "normal" : "strange");
  653. diff --git c/src/hack.c w/src/hack.c
  654. index d84dd35..4e9d32e 100644
  655. --- c/src/hack.c
  656. +++ w/src/hack.c
  657. @@ -220,8 +220,7 @@ moverock()
  658.                      deltrap(ttmp);
  659.                      delobj(otmp);
  660.                      bury_objs(rx, ry);
  661. -                    levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
  662. -                    levl[rx][ry].candig = 1;
  663. +                    levl[rx][ry].flags |= FL_DIGGABLE;
  664.                      if (cansee(rx, ry))
  665.                          newsym(rx, ry);
  666.                      return sobj_at(BOULDER, sx, sy) ? -1 : 0;
  667. @@ -2657,7 +2656,8 @@ lookaround()
  668.              if ((mtmp = m_at(x, y)) != 0
  669.                  && M_AP_TYPE(mtmp) != M_AP_FURNITURE
  670.                  && M_AP_TYPE(mtmp) != M_AP_OBJECT
  671. -                && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
  672. +                && (!minvisible(mtmp) || See_invisible)
  673. +                && !mtmp->mundetected) {
  674.                  if ((context.run != 1 && !mtmp->mtame)
  675.                      || (x == u.ux + u.dx && y == u.uy + u.dy
  676.                          && !context.travel)) {
  677. diff --git c/src/invent.c w/src/invent.c
  678. index ff69de7..b3b675c 100644
  679. --- c/src/invent.c
  680. +++ w/src/invent.c
  681. @@ -4384,6 +4384,9 @@ boolean as_if_seen;
  682.      menu_item *selected = 0;
  683.      int n;
  684.  
  685. +    if (!levl[x][y].buried)
  686. +        return 0; /* nothing to do here */
  687. +
  688.      /* count # of objects here */
  689.      for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
  690.          if (obj->ox == x && obj->oy == y) {
  691. diff --git c/src/light.c w/src/light.c
  692. index 446dc39..0c025fa 100644
  693. --- c/src/light.c
  694. +++ w/src/light.c
  695. @@ -41,6 +41,7 @@
  696.  /* flags */
  697.  #define LSF_SHOW 0x1        /* display the light source */
  698.  #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */
  699. +#define LSF_DETECT 0x4      /* guiding candle */
  700.  
  701.  static light_source *light_base = 0;
  702.  
  703. @@ -71,9 +72,9 @@ anything *id;
  704.      ls->x = x;
  705.      ls->y = y;
  706.      ls->range = range;
  707. -    ls->type = type;
  708. +    ls->type = type & ~LS_DETECT;
  709.      ls->id = *id;
  710. -    ls->flags = 0;
  711. +    ls->flags = type & LS_DETECT ? LSF_DETECT : 0;
  712.      light_base = ls;
  713.  
  714.      vision_full_recalc = 1; /* make the source show up */
  715. @@ -157,9 +158,10 @@ char **cs_rows;
  716.          /* minor optimization: don't bother with duplicate light sources */
  717.          /* at hero */
  718.          if (ls->x == u.ux && ls->y == u.uy) {
  719. -            if (at_hero_range >= ls->range)
  720. -                ls->flags &= ~LSF_SHOW;
  721. -            else
  722. +            if (at_hero_range >= ls->range) {
  723. +                if (!(ls->flags & LSF_DETECT))
  724. +                    ls->flags &= ~LSF_SHOW;
  725. +            } else
  726.                  at_hero_range = ls->range;
  727.          }
  728.  
  729. @@ -197,13 +199,19 @@ char **cs_rows;
  730.                       * does this.
  731.                       */
  732.                      for (x = min_x; x <= max_x; x++)
  733. -                        if (row[x] & COULD_SEE)
  734. +                        if (row[x] & COULD_SEE) {
  735.                              row[x] |= TEMP_LIT;
  736. +                            if (ls->flags & LSF_DETECT)
  737. +                                row[x] |= TEMP_DETECT;
  738. +                        }
  739.                  } else {
  740.                      for (x = min_x; x <= max_x; x++)
  741.                          if ((ls->x == x && ls->y == y)
  742. -                            || clear_path((int) ls->x, (int) ls->y, x, y))
  743. +                            || clear_path((int) ls->x, (int) ls->y, x, y)) {
  744.                              row[x] |= TEMP_LIT;
  745. +                            if (ls->flags & LSF_DETECT)
  746. +                                row[x] |= TEMP_DETECT;
  747. +                        }
  748.                  }
  749.              }
  750.          }
  751. @@ -602,10 +610,18 @@ struct obj *obj;
  752.  int new_radius;
  753.  {
  754.      light_source *ls;
  755. +    short old_flags;
  756.  
  757.      for (ls = light_base; ls; ls = ls->next)
  758.          if (ls->type == LS_OBJECT && ls->id.a_obj == obj) {
  759. -            if (new_radius != ls->range)
  760. +            old_flags = ls->flags;
  761. +            if (obj->otyp == GUIDING_CANDLE) {
  762. +                if (obj->cursed)
  763. +                    ls->flags &= ~LSF_DETECT;
  764. +                else
  765. +                    ls->flags |= LSF_DETECT;
  766. +            }
  767. +            if (new_radius != ls->range || ls->flags != old_flags)
  768.                  vision_full_recalc = 1;
  769.              ls->range = new_radius;
  770.              return;
  771. @@ -646,6 +662,8 @@ struct obj *obj;
  772.              radius++;
  773.              n /= 7L;
  774.          } while (n > 0L);
  775. +        if (obj->otyp == GUIDING_CANDLE && obj->blessed)
  776. +            radius++; /* make them less useless in late game */
  777.      } else {
  778.          /* we're only called for lit candelabrum or candles */
  779.          /* impossible("candlelight for %d?", obj->otyp); */
  780. @@ -656,7 +674,7 @@ struct obj *obj;
  781.  
  782.  /* light emitting artifact's range depends upon its curse/bless state */
  783.  int
  784. -arti_light_radius(obj)
  785. +dynamic_light_radius(obj)
  786.  struct obj *obj;
  787.  {
  788.      /*
  789. @@ -667,9 +685,12 @@ struct obj *obj;
  790.       */
  791.  
  792.      /* sanity check [simplifies usage by bless()/curse()/&c] */
  793. -    if (!obj->lamplit || !artifact_light(obj))
  794. +    if (!obj->lamplit || !artifact_light(obj) && obj->otyp != GUIDING_CANDLE)
  795.          return 0;
  796.  
  797. +    if (obj->otyp == GUIDING_CANDLE)
  798. +        return candle_light_range(obj);
  799. +
  800.      /* cursed radius of 1 is not noticeable for an item that's
  801.         carried by the hero but is if it's carried by a monster
  802.         or left lit on the floor (not applicable for Sunsword) */
  803. @@ -681,7 +702,7 @@ const char *
  804.  arti_light_description(obj)
  805.  struct obj *obj;
  806.  {
  807. -    switch (arti_light_radius(obj)) {
  808. +    switch (dynamic_light_radius(obj)) {
  809.      case 3:
  810.          return "brilliantly"; /* blessed */
  811.      case 2:
  812. diff --git c/src/mcastu.c w/src/mcastu.c
  813. index 1f73638..b59981a 100644
  814. --- c/src/mcastu.c
  815. +++ w/src/mcastu.c
  816. @@ -59,7 +59,7 @@ boolean undirected;
  817.  
  818.          if (undirected)
  819.              point_msg = "all around, then curses";
  820. -        else if ((Invis && !perceives(mtmp->data)
  821. +        else if ((Invis && !perceives_you(mtmp->data)
  822.                    && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  823.                   || is_obj_mappear(&youmonst, STRANGE_OBJECT)
  824.                   || u.uundetected)
  825. @@ -264,7 +264,7 @@ boolean foundyou;
  826.                canspotmon(mtmp) ? Monnam(mtmp) : "Something",
  827.                is_undirected_spell(mattk->adtyp, spellnum)
  828.                    ? ""
  829. -                  : (Invisible && !perceives(mtmp->data)
  830. +                  : (Invis && !perceives_you(mtmp->data)
  831.                       && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  832.                          ? " at a spot near you"
  833.                          : (Displaced
  834. @@ -414,7 +414,7 @@ int spellnum;
  835.  
  836.              /* messages not quite right if plural monsters created but
  837.                 only a single monster is seen */
  838. -            if (Invisible && !perceives(mtmp->data)
  839. +            if (Invis && !perceives_you(mtmp->data)
  840.                  && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  841.                  pline("%s around a spot near you!", mappear);
  842.              else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  843. @@ -463,7 +463,8 @@ int spellnum;
  844.          if (!mtmp->minvis && !mtmp->invis_blkd) {
  845.              if (canseemon(mtmp))
  846.                  pline("%s suddenly %s!", Monnam(mtmp),
  847. -                      !See_invisible ? "disappears" : "becomes transparent");
  848. +                      !See_invisible && !candetect(mtmp->mx, mtmp->my)
  849. +                      ? "disappears" : "becomes transparent");
  850.              mon_set_minvis(mtmp);
  851.              if (cansee(mtmp->mx, mtmp->my) && !canspotmon(mtmp))
  852.                  map_invisible(mtmp->mx, mtmp->my);
  853. @@ -640,7 +641,7 @@ int spellnum;
  854.              fmt = "%s casts at a clump of sticks, but nothing happens.";
  855.          else if (let == S_SNAKE)
  856.              fmt = "%s transforms a clump of sticks into snakes!";
  857. -        else if (Invisible && !perceives(mtmp->data)
  858. +        else if (Invis && !perceives_you(mtmp->data)
  859.                   && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  860.              fmt = "%s summons insects around a spot near you!";
  861.          else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
  862. diff --git c/src/mhitm.c w/src/mhitm.c
  863. index 79f1e67..2320b2e 100644
  864. --- c/src/mhitm.c
  865. +++ w/src/mhitm.c
  866. @@ -609,7 +609,7 @@ struct attack *mattk;
  867.      }
  868.  
  869.      if (magr->mcan || !magr->mcansee || !mdef->mcansee
  870. -        || (magr->minvis && !perceives(mdef->data)) || mdef->msleeping) {
  871. +        || (minvisible(magr) && !perceives(mdef->data)) || mdef->msleeping) {
  872.          if (vis && canspotmon(mdef))
  873.              pline("but nothing happens.");
  874.          return MM_MISS;
  875. @@ -625,7 +625,7 @@ struct attack *mattk;
  876.                                        "The gaze is reflected away by %s %s.");
  877.                  return MM_MISS;
  878.              }
  879. -            if (mdef->minvis && !perceives(magr->data)) {
  880. +            if (minvisible(mdef) && !perceives(magr->data)) {
  881.                  if (canseemon(magr)) {
  882.                      pline(
  883.                        "%s doesn't seem to notice that %s gaze was reflected.",
  884. @@ -1590,7 +1590,7 @@ int mdead;
  885.                  if (!rn2(4))
  886.                      tmp = 127;
  887.                  if (magr->mcansee && haseyes(madat) && mdef->mcansee
  888. -                    && (perceives(madat) || !mdef->minvis)) {
  889. +                    && (perceives(madat) || !minvisible(mdef))) {
  890.                      /* construct format string; guard against '%' in Monnam */
  891.                      Strcpy(buf, s_suffix(Monnam(mdef)));
  892.                      (void) strNsubst(buf, "%", "%%", 0);
  893. diff --git c/src/mhitu.c w/src/mhitu.c
  894. index db92458..1927d01 100644
  895. --- c/src/mhitu.c
  896. +++ w/src/mhitu.c
  897. @@ -159,7 +159,7 @@ struct attack *mattk;
  898.                ? could_seduce(mtmp, &youmonst, mattk) : 0);
  899.      Monst_name = Monnam(mtmp);
  900.  
  901. -    if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
  902. +    if (!mtmp->mcansee || (Invis && !perceives_you(mtmp->data))) {
  903.          const char *swings = (mattk->aatyp == AT_BITE) ? "snaps"
  904.                               : (mattk->aatyp == AT_KICK) ? "kicks"
  905.                                 : (mattk->aatyp == AT_STNG
  906. @@ -573,7 +573,7 @@ register struct monst *mtmp;
  907.      tmp += mtmp->m_lev;
  908.      if (multi < 0)
  909.          tmp += 4;
  910. -    if ((Invis && !perceives(mdat)) || !mtmp->mcansee)
  911. +    if ((Invis && !perceives_you(mdat)) || !mtmp->mcansee)
  912.          tmp -= 2;
  913.      if (mtmp->mtrapped)
  914.          tmp -= 2;
  915. @@ -2386,16 +2386,18 @@ struct attack *mattk; /* non-Null: current attack; Null: general capability */
  916.          pagr = youmonst.data;
  917.          agrinvis = (Invis != 0);
  918.          genagr = poly_gender();
  919. +        defperc = candetect(u.ux, u.uy);
  920.      } else {
  921.          pagr = magr->data;
  922.          agrinvis = magr->minvis;
  923.          genagr = gender(magr);
  924. +        defperc = candetect(magr->mx, magr->my);
  925.      }
  926.      if (mdef == &youmonst) {
  927. -        defperc = (See_invisible != 0);
  928. +        defperc = defperc || See_invisible;
  929.          gendef = poly_gender();
  930.      } else {
  931. -        defperc = perceives(mdef->data);
  932. +        defperc = defperc || perceives(mdef->data);
  933.          gendef = gender(mdef);
  934.      }
  935.  
  936. @@ -2873,7 +2875,7 @@ struct attack *mattk;
  937.                  if (!rn2(4))
  938.                      tmp = 127;
  939.                  if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3)
  940. -                    && (perceives(mtmp->data) || !Invis)) {
  941. +                    && (perceives_you(mtmp->data) || !Invis)) {
  942.                      if (Blind)
  943.                          pline("As a blind %s, you cannot defend yourself.",
  944.                                youmonst.data->mname);
  945. diff --git c/src/mkobj.c w/src/mkobj.c
  946. index 195de0b..1909852 100644
  947. --- c/src/mkobj.c
  948. +++ w/src/mkobj.c
  949. @@ -10,6 +10,7 @@ STATIC_DCL unsigned FDECL(nextoid, (struct obj *, struct obj *));
  950.  STATIC_DCL void FDECL(maybe_adjust_light, (struct obj *, int));
  951.  STATIC_DCL void FDECL(obj_timer_checks, (struct obj *,
  952.                                           XCHAR_P, XCHAR_P, int));
  953. +STATIC_DCL void FDECL(recheck_buried, (int, int));
  954.  STATIC_DCL void FDECL(container_weight, (struct obj *));
  955.  STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *));
  956.  STATIC_DCL void FDECL(objlist_sanity, (struct obj *, int, const char *));
  957. @@ -898,11 +899,12 @@ boolean artif;
  958.              switch (otmp->otyp) {
  959.              case TALLOW_CANDLE:
  960.              case WAX_CANDLE:
  961. -                otmp->spe = 1;
  962. -                otmp->age = 20L * /* 400 or 200 */
  963. -                            (long) objects[otmp->otyp].oc_cost;
  964. -                otmp->lamplit = 0;
  965.                  otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
  966. +                /*FALLTHRU*/
  967. +            case GUIDING_CANDLE:
  968. +                otmp->spe = 1;
  969. +                otmp->age = candle_burn_time(otmp);
  970. +                otmp->lamplit = 0;
  971.                  blessorcurse(otmp, 5);
  972.                  break;
  973.              case BRASS_LANTERN:
  974. @@ -1227,12 +1229,13 @@ int old_range;
  975.  {
  976.      char buf[BUFSZ];
  977.      xchar ox, oy;
  978. -    int new_range = arti_light_radius(obj), delta = new_range - old_range;
  979. +    int new_range = dynamic_light_radius(obj), delta = new_range - old_range;
  980.  
  981.      /* radius of light emitting artifact varies by curse/bless state
  982.         so will change after blessing or cursing */
  983. -    if (delta) {
  984. +    if (new_range)
  985.          obj_adjust_light_radius(obj, new_range);
  986. +    if (delta) {
  987.          /* simplifying assumptions:  hero is wielding this object;
  988.             artifacts have to be in use to emit light and monsters'
  989.             gear won't change bless or curse state */
  990. @@ -1249,7 +1252,8 @@ int old_range;
  991.                     when changing intensity, using "less brightly" is
  992.                     straightforward for dimming, but we need "brighter"
  993.                     rather than "more brightly" for brightening; ugh */
  994. -                pline("%s %s %s%s.", buf, otense(obj, "shine"),
  995. +                pline("%s %s %s%s.", buf, otense(obj, Is_candle(obj)
  996. +                                                      ? "burn" : "shine"),
  997.                        (abs(delta) > 1) ? "much " : "",
  998.                        (delta > 0) ? "brighter" : "less brightly");
  999.              }
  1000. @@ -1272,7 +1276,7 @@ register struct obj *otmp;
  1001.      if (otmp->oclass == COIN_CLASS)
  1002.          return;
  1003.      if (otmp->lamplit)
  1004. -        old_light = arti_light_radius(otmp);
  1005. +        old_light = dynamic_light_radius(otmp);
  1006.      otmp->cursed = 0;
  1007.      otmp->blessed = 1;
  1008.      if (carried(otmp) && confers_luck(otmp))
  1009. @@ -1293,7 +1297,7 @@ register struct obj *otmp;
  1010.      int old_light = 0;
  1011.  
  1012.      if (otmp->lamplit)
  1013. -        old_light = arti_light_radius(otmp);
  1014. +        old_light = dynamic_light_radius(otmp);
  1015.      otmp->blessed = 0;
  1016.      if (carried(otmp) && confers_luck(otmp))
  1017.          set_moreluck();
  1018. @@ -1313,7 +1317,7 @@ register struct obj *otmp;
  1019.      if (otmp->oclass == COIN_CLASS)
  1020.          return;
  1021.      if (otmp->lamplit)
  1022. -        old_light = arti_light_radius(otmp);
  1023. +        old_light = dynamic_light_radius(otmp);
  1024.      already_cursed = otmp->cursed;
  1025.      otmp->blessed = 0;
  1026.      otmp->cursed = 1;
  1027. @@ -1350,7 +1354,7 @@ register struct obj *otmp;
  1028.      int old_light = 0;
  1029.  
  1030.      if (otmp->lamplit)
  1031. -        old_light = arti_light_radius(otmp);
  1032. +        old_light = dynamic_light_radius(otmp);
  1033.      otmp->cursed = 0;
  1034.      if (carried(otmp) && confers_luck(otmp))
  1035.          set_moreluck();
  1036. @@ -1768,7 +1772,7 @@ boolean do_buried;
  1037.          if (otmp->timed)
  1038.              obj_timer_checks(otmp, x, y, 0);
  1039.      }
  1040. -    if (do_buried) {
  1041. +    if (do_buried && levl[x][y].buried) {
  1042.          for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
  1043.              if (otmp->ox == x && otmp->oy == y) {
  1044.                  if (otmp->timed)
  1045. @@ -1955,6 +1959,7 @@ struct obj *obj;
  1046.          break;
  1047.      case OBJ_BURIED:
  1048.          extract_nobj(obj, &level.buriedobjlist);
  1049. +        recheck_buried(obj->ox, obj->oy);
  1050.          break;
  1051.      case OBJ_ONBILL:
  1052.          extract_nobj(obj, &billobjs);
  1053. @@ -2095,6 +2100,21 @@ struct obj *obj;
  1054.      obj->where = OBJ_BURIED;
  1055.      obj->nobj = level.buriedobjlist;
  1056.      level.buriedobjlist = obj;
  1057. +    levl[obj->ox][obj->oy].buried = 1;
  1058. +}
  1059. +
  1060. +STATIC_OVL void
  1061. +recheck_buried(x, y)
  1062. +int x, y;
  1063. +{
  1064. +    struct obj *obj;
  1065. +    for (obj = level.buriedobjlist; obj; obj = obj->nobj)
  1066. +        if (obj->ox == x && obj->oy == y)
  1067. +          {
  1068. +            levl[x][y].buried = 1;
  1069. +            return;
  1070. +          }
  1071. +    levl[x][y].buried = 0;
  1072.  }
  1073.  
  1074.  /* Recalculate the weight of this container and all of _its_ containers. */
  1075. diff --git c/src/mon.c w/src/mon.c
  1076. index 7bb0d0f..a811f5c 100644
  1077. --- c/src/mon.c
  1078. +++ w/src/mon.c
  1079. @@ -1405,7 +1405,7 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
  1080.                  && (lavaok || !is_lava(nx, ny))) {
  1081.                  int dispx, dispy;
  1082.                  boolean monseeu = (mon->mcansee
  1083. -                                   && (!Invis || perceives(mdat)));
  1084. +                                   && (!Invis || perceives_you(mdat)));
  1085.                  boolean checkobj = OBJ_AT(nx, ny);
  1086.  
  1087.                  /* Displacement also displaces the Elbereth/scare monster,
  1088. @@ -2917,9 +2917,9 @@ int x, y, distance;
  1089.      }
  1090.  }
  1091.  
  1092. -/* NOTE: we must check for mimicry before calling this routine */
  1093. +/* also used in detect.c */
  1094.  void
  1095. -seemimic(mtmp)
  1096. +seemimic_noredraw(mtmp)
  1097.  register struct monst *mtmp;
  1098.  {
  1099.      boolean is_blocker_appear = (is_lightblocker_mappear(mtmp));
  1100. @@ -2936,7 +2936,14 @@ register struct monst *mtmp;
  1101.      if (is_blocker_appear
  1102.          && !does_block(mtmp->mx, mtmp->my, &levl[mtmp->mx][mtmp->my]))
  1103.          unblock_point(mtmp->mx, mtmp->my);
  1104. +}
  1105.  
  1106. +/* NOTE: we must check for mimicry before calling this routine */
  1107. +void
  1108. +seemimic(mtmp)
  1109. +register struct monst *mtmp;
  1110. +{
  1111. +    seemimic_noredraw(mtmp);
  1112.      newsym(mtmp->mx, mtmp->my);
  1113.  }
  1114.  
  1115. diff --git c/src/monmove.c w/src/monmove.c
  1116. index 2f7ae6f..e832a23 100644
  1117. --- c/src/monmove.c
  1118. +++ w/src/monmove.c
  1119. @@ -330,7 +330,7 @@ int *inrange, *nearby, *scared;
  1120.       * running into you by accident but possibly attacking the spot
  1121.       * where it guesses you are.
  1122.       */
  1123. -    if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
  1124. +    if (!mtmp->mcansee || (Invis && !perceives_you(mtmp->data))) {
  1125.          seescaryx = mtmp->mux;
  1126.          seescaryy = mtmp->muy;
  1127.      } else {
  1128. @@ -913,7 +913,7 @@ register int after;
  1129.                                && (dist2(omx, omy, gx, gy) <= 36));
  1130.  
  1131.          if (!mtmp->mcansee
  1132. -            || (should_see && Invis && !perceives(ptr) && rn2(11))
  1133. +            || (should_see && Invis && !perceives_you(ptr) && rn2(11))
  1134.              || is_obj_mappear(&youmonst,STRANGE_OBJECT) || u.uundetected
  1135.              || (is_obj_mappear(&youmonst,GOLD_PIECE) && !likes_gold(ptr))
  1136.              || (mtmp->mpeaceful && !mtmp->isshk) /* allow shks to follow */
  1137. @@ -1550,7 +1550,7 @@ register struct monst *mtmp;
  1138.      if (mx == u.ux && my == u.uy)
  1139.          goto found_you;
  1140.  
  1141. -    notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data)));
  1142. +    notseen = (!mtmp->mcansee || (Invis && !perceives_you(mtmp->data)));
  1143.      /* add cases as required.  eg. Displacement ... */
  1144.      if (notseen || Underwater) {
  1145.          /* Xorns can smell quantities of valuable metal
  1146. diff --git c/src/mthrowu.c w/src/mthrowu.c
  1147. index d10d2f1..9e0b1bd 100644
  1148. --- c/src/mthrowu.c
  1149. +++ w/src/mthrowu.c
  1150. @@ -1159,8 +1159,8 @@ int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
  1151.              break;
  1152.          case TOOL_CLASS:
  1153.              hits = (obj_type != SKELETON_KEY && obj_type != LOCK_PICK
  1154. -                    && obj_type != CREDIT_CARD && obj_type != TALLOW_CANDLE
  1155. -                    && obj_type != WAX_CANDLE && obj_type != LENSES
  1156. +                    && obj_type != CREDIT_CARD && !Is_candle(otmp)
  1157. +                    && obj_type != LENSES
  1158.                      && obj_type != TIN_WHISTLE && obj_type != MAGIC_WHISTLE);
  1159.              break;
  1160.          case ROCK_CLASS: /* includes boulder */
  1161. diff --git c/src/muse.c w/src/muse.c
  1162. index ec533c0..c2b0880 100644
  1163. --- c/src/muse.c
  1164. +++ w/src/muse.c
  1165. @@ -727,7 +727,7 @@ struct monst *mtmp;
  1166.              pline_The("digging ray is ineffective.");
  1167.              return 2;
  1168.          }
  1169. -        if (!Can_dig_down(&u.uz) && !levl[mtmp->mx][mtmp->my].candig) {
  1170. +        if (!Can_dig_hole(mtmp->mx, mtmp->my, &u.uz)) {
  1171.              if (canseemon(mtmp))
  1172.                  pline_The("%s here is too hard to dig in.",
  1173.                            surface(mtmp->mx, mtmp->my));
  1174. diff --git c/src/objects.c w/src/objects.c
  1175. index fcca3b0..a3f8c99 100644
  1176. --- c/src/objects.c
  1177. +++ w/src/objects.c
  1178. @@ -658,8 +658,9 @@ TOOL("skeleton key",       "key", 0, 0, 0, 0, 80,  3, 10, IRON, HI_METAL),
  1179.  TOOL("lock pick",           None, 1, 0, 0, 0, 60,  4, 20, IRON, HI_METAL),
  1180.  TOOL("credit card",         None, 1, 0, 0, 0, 15,  1, 10, PLASTIC, CLR_WHITE),
  1181.  /* light sources */
  1182. -TOOL("tallow candle",   "candle", 0, 1, 0, 0, 20,  2, 10, WAX, CLR_WHITE),
  1183. +TOOL("tallow candle",   "candle", 0, 1, 0, 0, 17,  2, 10, WAX, CLR_WHITE),
  1184.  TOOL("wax candle",      "candle", 0, 1, 0, 0,  5,  2, 20, WAX, CLR_WHITE),
  1185. +TOOL("guiding candle",  "candle", 0, 1, 1, 0,  3,  2, 30, WAX, CLR_WHITE),
  1186.  TOOL("brass lantern",       None, 1, 0, 0, 0, 30, 30, 12, COPPER, CLR_YELLOW),
  1187.  TOOL("oil lamp",          "lamp", 0, 0, 0, 0, 45, 20, 10, COPPER, CLR_YELLOW),
  1188.  TOOL("magic lamp",        "lamp", 0, 0, 1, 0, 15, 20, 50, COPPER, CLR_YELLOW),
  1189. diff --git c/src/objnam.c w/src/objnam.c
  1190. index 06efd9b..cb0f06d 100644
  1191. --- c/src/objnam.c
  1192. +++ w/src/objnam.c
  1193. @@ -1077,8 +1077,7 @@ unsigned doname_flags;
  1194.              break;
  1195.          } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
  1196.                     || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
  1197. -            if (Is_candle(obj)
  1198. -                && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
  1199. +            if (Is_candle(obj) && obj->age < candle_burn_time(obj))
  1200.                  Strcat(prefix, "partly used ");
  1201.              if (obj->lamplit)
  1202.                  Strcat(bp, " (lit)");
  1203. @@ -2668,7 +2667,7 @@ struct o_range {
  1204.  STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
  1205.      { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
  1206.      { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
  1207. -    { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
  1208. +    { "candle", TOOL_CLASS, TALLOW_CANDLE, GUIDING_CANDLE },
  1209.      { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
  1210.      { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
  1211.      { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
  1212. @@ -3707,7 +3706,7 @@ struct obj *no_wish;
  1213.              typ = FAKE_AMULET_OF_YENDOR;
  1214.              break;
  1215.          case CANDELABRUM_OF_INVOCATION:
  1216. -            typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
  1217. +            typ = rnd_class(TALLOW_CANDLE, GUIDING_CANDLE);
  1218.              break;
  1219.          case BELL_OF_OPENING:
  1220.              typ = BELL;
  1221. @@ -3741,7 +3740,8 @@ struct obj *no_wish;
  1222.  
  1223.      /* if player specified a reasonable count, maybe honor it */
  1224.      if (cnt > 0 && objects[typ].oc_merge
  1225. -        && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
  1226. +        && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp)
  1227. +                                       && !objects[typ].oc_magic)
  1228.              || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
  1229.                                || typ == ROCK || is_missile(otmp)))))
  1230.          otmp->quan = (long) cnt;
  1231. diff --git c/src/pager.c w/src/pager.c
  1232. index 5ca886d..0b2b07e 100644
  1233. --- c/src/pager.c
  1234. +++ w/src/pager.c
  1235. @@ -167,7 +167,7 @@ struct obj **obj_p;
  1236.  
  1237.      *obj_p = (struct obj *) 0;
  1238.      /* TODO: check inside containers in case glyph came from detection */
  1239. -    if ((otmp = sobj_at(glyphotyp, x, y)) == 0)
  1240. +    if ((otmp = sobj_at(glyphotyp, x, y)) == 0 && levl[x][y].buried)
  1241.          for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj)
  1242.              if (otmp->ox == x && otmp->oy == y && otmp->otyp == glyphotyp)
  1243.                  break;
  1244. diff --git c/src/polyself.c w/src/polyself.c
  1245. index a8e4342..d8ff152 100644
  1246. --- c/src/polyself.c
  1247. +++ w/src/polyself.c
  1248. @@ -1320,9 +1320,9 @@ dogaze()
  1249.              continue;
  1250.          if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
  1251.              looked++;
  1252. -            if (Invis && !perceives(mtmp->data)) {
  1253. +            if (Invis && !perceives_you(mtmp->data)) {
  1254.                  pline("%s seems not to notice your gaze.", Monnam(mtmp));
  1255. -            } else if (mtmp->minvis && !See_invisible) {
  1256. +            } else if (minvisible(mtmp) && !See_invisible) {
  1257.                  You_cant("see where to gaze at %s.", Monnam(mtmp));
  1258.              } else if (M_AP_TYPE(mtmp) == M_AP_FURNITURE
  1259.                         || M_AP_TYPE(mtmp) == M_AP_OBJECT) {
  1260. diff --git c/src/potion.c w/src/potion.c
  1261. index 7d8afd0..5596433 100644
  1262. --- c/src/potion.c
  1263. +++ w/src/potion.c
  1264. @@ -439,7 +439,8 @@ self_invis_message()
  1265.      pline("%s %s.",
  1266.            Hallucination ? "Far out, man!  You"
  1267.                          : "Gee!  All of a sudden, you",
  1268. -          See_invisible ? "can see right through yourself"
  1269. +          See_invisible || candetect(u.ux, u.uy)
  1270. +                        ? "can see right through yourself"
  1271.                          : "can't see yourself");
  1272.  }
  1273.  
  1274. @@ -1680,8 +1681,9 @@ register struct obj *obj;
  1275.          if (!Blind && !Invis) {
  1276.              kn++;
  1277.              pline("For an instant you %s!",
  1278. -                  See_invisible ? "could see right through yourself"
  1279. -                                : "couldn't see yourself");
  1280. +                  See_invisible || candetect(u.ux, u.uy)
  1281. +                  ? "could see right through yourself"
  1282. +                  : "couldn't see yourself");
  1283.          }
  1284.          break;
  1285.      case POT_PARALYSIS:
  1286. diff --git c/src/priest.c w/src/priest.c
  1287. index d97886c..646fe5c 100644
  1288. --- c/src/priest.c
  1289. +++ w/src/priest.c
  1290. @@ -213,7 +213,7 @@ register struct monst *priest;
  1291.              }
  1292.              avoid = FALSE;
  1293.          }
  1294. -    } else if (Invis)
  1295. +    } else if (Invis && !perceives_you(priest->data))
  1296.          avoid = FALSE;
  1297.  
  1298.      return move_special(priest, FALSE, TRUE, FALSE, avoid, omx, omy, gx, gy);
  1299. diff --git c/src/save.c w/src/save.c
  1300. index c3ce6d0..efce8d3 100644
  1301. --- c/src/save.c
  1302. +++ w/src/save.c
  1303. @@ -580,7 +580,7 @@ boolean rlecomp;
  1304.                      && prm->flags == rgrm->flags && prm->lit == rgrm->lit
  1305.                      && prm->waslit == rgrm->waslit
  1306.                      && prm->roomno == rgrm->roomno && prm->edge == rgrm->edge
  1307. -                    && prm->candig == rgrm->candig) {
  1308. +                    && prm->buried == rgrm->buried) {
  1309.                      match++;
  1310.                      if (match > 254) {
  1311.                          match = 254; /* undo this match */
  1312. diff --git c/src/shk.c w/src/shk.c
  1313. index d5ad782..8ea5562 100644
  1314. --- c/src/shk.c
  1315. +++ w/src/shk.c
  1316. @@ -579,7 +579,7 @@ char *enterstring;
  1317.      if (muteshk(shkp) || eshkp->following)
  1318.          return; /* no dialog */
  1319.  
  1320. -    if (Invis) {
  1321. +    if (Invis && !perceives_you(shkp->data)) {
  1322.          pline("%s senses your presence.", Shknam(shkp));
  1323.          if (!Deaf && !muteshk(shkp))
  1324.              verbalize("Invisible customers are not welcome!");
  1325. @@ -2177,8 +2177,7 @@ boolean unpaid_only;
  1326.              if (saleable(shkp, otmp) && !otmp->unpaid
  1327.                  && otmp->oclass != BALL_CLASS
  1328.                  && !(otmp->oclass == FOOD_CLASS && otmp->oeaten)
  1329. -                && !(Is_candle(otmp)
  1330. -                     && otmp->age < 20L * (long) objects[otmp->otyp].oc_cost))
  1331. +                && !(Is_candle(otmp) && otmp->age < candle_burn_time(otmp)))
  1332.                  price += set_cost(otmp, shkp);
  1333.          } else {
  1334.              /* no_charge is only set for floor items (including
  1335. @@ -3117,8 +3116,7 @@ xchar x, y;
  1336.      if ((!saleitem && !(container && cltmp > 0L)) || eshkp->billct == BILLSZ
  1337.          || obj->oclass == BALL_CLASS || obj->oclass == CHAIN_CLASS
  1338.          || offer == 0L || (obj->oclass == FOOD_CLASS && obj->oeaten)
  1339. -        || (Is_candle(obj)
  1340. -            && obj->age < 20L * (long) objects[obj->otyp].oc_cost)) {
  1341. +        || (Is_candle(obj) && obj->age < candle_burn_time(obj))) {
  1342.          pline("%s seems uninterested%s.", Shknam(shkp),
  1343.                cgold ? " in the rest" : "");
  1344.          if (container)
  1345. @@ -3373,8 +3371,7 @@ boolean shk_buying;
  1346.              tmp += 10L * (long) obj->spe;
  1347.          break;
  1348.      case TOOL_CLASS:
  1349. -        if (Is_candle(obj)
  1350. -            && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
  1351. +        if (Is_candle(obj) && obj->age < candle_burn_time(obj))
  1352.              tmp /= 2L;
  1353.          break;
  1354.      }
  1355. @@ -3848,7 +3845,7 @@ struct monst *shkp;
  1356.          avoid = FALSE;
  1357.      } else {
  1358.  #define GDIST(x, y) (dist2(x, y, gx, gy))
  1359. -        if (Invis || u.usteed) {
  1360. +        if (Invis && !perceives_you(shkp->data) || u.usteed) {
  1361.              avoid = FALSE;
  1362.          } else {
  1363.              uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
  1364. @@ -4178,7 +4175,7 @@ boolean cant_mollify;
  1365.          return;
  1366.      }
  1367.  
  1368. -    if (Invis)
  1369. +    if (Invis && !perceives_you(shkp->data))
  1370.          Your("invisibility does not fool %s!", shkname(shkp));
  1371.      Sprintf(qbuf, "%sYou did %ld %s worth of damage!%s  Pay?",
  1372.              !animal ? cad(TRUE) : "", cost_of_damage,
  1373. @@ -4630,7 +4627,8 @@ register xchar x, y;
  1374.          && shkp->mcanmove && !shkp->msleeping
  1375.          && (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
  1376.          pline("%s%s blocks your way!", Shknam(shkp),
  1377. -              Invis ? " senses your motion and" : "");
  1378. +              Invis && !perceives_you(shkp->data) ? " senses your motion and"
  1379. +                                                  : "");
  1380.          return TRUE;
  1381.      }
  1382.      return FALSE;
  1383. @@ -4664,10 +4662,11 @@ register xchar x, y;
  1384.  
  1385.      if (shkp->mx == sx && shkp->my == sy && shkp->mcanmove && !shkp->msleeping
  1386.          && (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
  1387. -        && (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
  1388. -            || u.usteed)) {
  1389. +        && (Invis && !perceives_you(shkp->data) || carrying(PICK_AXE)
  1390. +            || carrying(DWARVISH_MATTOCK) || u.usteed)) {
  1391.          pline("%s%s blocks your way!", Shknam(shkp),
  1392. -              Invis ? " senses your motion and" : "");
  1393. +              Invis && !perceives_you(shkp->data) ? " senses your motion and"
  1394. +                                                  : "");
  1395.          return TRUE;
  1396.      }
  1397.      return FALSE;
  1398. diff --git c/src/shknam.c w/src/shknam.c
  1399. index a36b67e..cb54cc7 100644
  1400. --- c/src/shknam.c
  1401. +++ w/src/shknam.c
  1402. @@ -330,8 +330,9 @@ const struct shclass shtypes[] = {
  1403.        TOOL_CLASS,
  1404.        0,
  1405.        D_SHOP,
  1406. -      { { 30, -WAX_CANDLE },
  1407. -        { 48, -TALLOW_CANDLE },
  1408. +      { { 25, -WAX_CANDLE },
  1409. +        { 38, -TALLOW_CANDLE },
  1410. +        { 15, -GUIDING_CANDLE },
  1411.          { 5, -BRASS_LANTERN },
  1412.          { 9, -OIL_LAMP },
  1413.          { 3, -MAGIC_LAMP },
  1414. diff --git c/src/timeout.c w/src/timeout.c
  1415. index a4408de..c02319f 100644
  1416. --- c/src/timeout.c
  1417. +++ w/src/timeout.c
  1418. @@ -594,7 +594,7 @@ nh_timeout()
  1419.              case INVIS:
  1420.                  newsym(u.ux, u.uy);
  1421.                  if (!Invis && !BInvis && !Blind) {
  1422. -                    You(!See_invisible
  1423. +                    You(!See_invisible && !candetect(u.ux, u.uy)
  1424.                              ? "are no longer invisible."
  1425.                              : "can no longer see through yourself.");
  1426.                      stop_occupation();
  1427. @@ -1249,6 +1249,7 @@ long timeout;
  1428.      case CANDELABRUM_OF_INVOCATION:
  1429.      case TALLOW_CANDLE:
  1430.      case WAX_CANDLE:
  1431. +    case GUIDING_CANDLE:
  1432.          switch (obj->age) {
  1433.          case 75:
  1434.              if (canseeit)
  1435. @@ -1411,6 +1412,7 @@ boolean already_lit;
  1436.      int radius = 3;
  1437.      long turns = 0;
  1438.      boolean do_timer = TRUE;
  1439. +    boolean detect = FALSE;
  1440.  
  1441.      if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj))
  1442.          return;
  1443. @@ -1443,6 +1445,10 @@ boolean already_lit;
  1444.              turns = obj->age;
  1445.          break;
  1446.  
  1447. +    case GUIDING_CANDLE:
  1448. +        if (!obj->cursed)
  1449. +            detect = TRUE;
  1450. +        /* fall through */
  1451.      case CANDELABRUM_OF_INVOCATION:
  1452.      case TALLOW_CANDLE:
  1453.      case WAX_CANDLE:
  1454. @@ -1461,7 +1467,7 @@ boolean already_lit;
  1455.          if (artifact_light(obj)) {
  1456.              obj->lamplit = 1;
  1457.              do_timer = FALSE;
  1458. -            radius = arti_light_radius(obj);
  1459. +            radius = dynamic_light_radius(obj);
  1460.          } else {
  1461.              impossible("begin burn: unexpected %s", xname(obj));
  1462.              turns = obj->age;
  1463. @@ -1487,7 +1493,9 @@ boolean already_lit;
  1464.          xchar x, y;
  1465.  
  1466.          if (get_obj_location(obj, &x, &y, CONTAINED_TOO | BURIED_TOO))
  1467. -            new_light_source(x, y, radius, LS_OBJECT, obj_to_any(obj));
  1468. +            new_light_source(x, y, radius,
  1469. +                             detect ? LS_OBJECT | LS_DETECT : LS_OBJECT,
  1470. +                             obj_to_any(obj));
  1471.          else
  1472.              impossible("begin_burn: can't get obj position");
  1473.      }
  1474. diff --git c/src/trap.c w/src/trap.c
  1475. index 02d1030..7a06ff0 100644
  1476. --- c/src/trap.c
  1477. +++ w/src/trap.c
  1478. @@ -487,7 +487,7 @@ boolean td; /* td == TRUE : trap door or hole */
  1479.      if (Sokoban && Can_fall_thru(&u.uz))
  1480.          ; /* KMH -- You can't escape the Sokoban level traps */
  1481.      else if (Levitation || u.ustuck
  1482. -             || (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig) || Flying
  1483. +             || !Can_fall_thru(&u.uz) || Flying
  1484.               || is_clinger(youmonst.data)
  1485.               || (Inhell && !u.uevent.invoked && newlevel == bottom)) {
  1486.          dont_fall = "don't fall in.";
  1487. diff --git c/src/uhitm.c w/src/uhitm.c
  1488. index f478d02..fdbc616 100644
  1489. --- c/src/uhitm.c
  1490. +++ w/src/uhitm.c
  1491. @@ -3008,7 +3008,7 @@ struct monst *mtmp;
  1492.  
  1493.          /* cloned Wiz starts out mimicking some other monster and
  1494.             might make himself invisible before being revealed */
  1495. -        if (mtmp->minvis && !See_invisible)
  1496. +        if (minvisible(mtmp) && !See_invisible)
  1497.              what = generic;
  1498.          else
  1499.              what = a_monnam(mtmp);
  1500. diff --git c/src/vision.c w/src/vision.c
  1501. index b8ce2e5..2b95930 100644
  1502. --- c/src/vision.c
  1503. +++ w/src/vision.c
  1504. @@ -513,6 +513,7 @@ int control;
  1505.      int dx, dy;        /* one step from a lit door or lit wall (see below) */
  1506.      register int col;  /* inner loop counter */
  1507.      register struct rm *lev; /* pointer to current pos */
  1508. +    struct obj *otmp;  /* for iterating through inventory */
  1509.      struct rm *flev; /* pointer to position in "front" of current pos */
  1510.      extern unsigned char seenv_matrix[3][3]; /* from display.c */
  1511.      static unsigned char colbump[COLNO + 1]; /* cols to bump sv */
  1512. @@ -570,6 +571,17 @@ int control;
  1513.                      newsym(col, row);
  1514.          }
  1515.  
  1516. +        /* Check if the invisible hero can be seen because of their guiding
  1517. +         * candle (normally would be checked below).  We don't check for
  1518. +         * nearby candles (on the ground or held by monsters) because that's
  1519. +         * too much effort for too rare an occurence.
  1520. +         */
  1521. +        for (otmp = invent; otmp; otmp = otmp->nobj)
  1522. +            if (otmp->otyp == GUIDING_CANDLE && otmp->lamplit) {
  1523. +                viz_array[u.uy][u.ux] |= TEMP_DETECT;
  1524. +                break;
  1525. +            }
  1526. +
  1527.          /* skip the normal update loop */
  1528.          goto skip;
  1529.      } else if (Is_rogue_level(&u.uz)) {
  1530. @@ -737,8 +749,10 @@ int control;
  1531.                  lev->seenv |=
  1532.                      new_angle(lev, sv, row, col); /* update seen angle */
  1533.  
  1534. -                /* Update pos if previously not in sight or new angle. */
  1535. -                if (!(old_row[col] & IN_SIGHT) || oldseenv != lev->seenv)
  1536. +                /* Update pos if previously not in sight or new angle
  1537. +                 * or when entering/leaving the radius of guiding candle. */
  1538. +                if (!(old_row[col] & IN_SIGHT) || oldseenv != lev->seenv
  1539. +                    || (old_row[col] ^ next_row[col]) & TEMP_DETECT)
  1540.                      newsym(col, row);
  1541.  
  1542.              } else if ((next_row[col] & COULD_SEE)
  1543. @@ -766,9 +780,11 @@ int control;
  1544.                          lev->seenv |= new_angle(lev, sv, row, col);
  1545.  
  1546.                          /* Update pos if previously not in sight or new
  1547. -                         * angle.*/
  1548. +                         * angle or when entering/leaving the radius of
  1549. +                         * guiding candle. */
  1550.                          if (!(old_row[col] & IN_SIGHT)
  1551. -                            || oldseenv != lev->seenv)
  1552. +                            || oldseenv != lev->seenv
  1553. +                            || (old_row[col] ^ next_row[col]) & TEMP_DETECT)
  1554.                              newsym(col, row);
  1555.                      } else
  1556.                          goto not_in_sight; /* we don't see it */
  1557. @@ -779,8 +795,10 @@ int control;
  1558.                      oldseenv = lev->seenv;
  1559.                      lev->seenv |= new_angle(lev, sv, row, col);
  1560.  
  1561. -                    /* Update pos if previously not in sight or new angle. */
  1562. -                    if (!(old_row[col] & IN_SIGHT) || oldseenv != lev->seenv)
  1563. +                    /* Update pos if previously not in sight or new angle or
  1564. +                     * when entering/leaving the radius of guiding candle. */
  1565. +                    if (!(old_row[col] & IN_SIGHT) || oldseenv != lev->seenv
  1566. +                        || (old_row[col] ^ next_row[col]) & TEMP_DETECT)
  1567.                          newsym(col, row);
  1568.                  }
  1569.              } else if ((next_row[col] & COULD_SEE) && lev->waslit) {
  1570. @@ -2806,7 +2824,7 @@ struct monst *mon;
  1571.      if (useemon && mon->minvis)
  1572.          how_seen |= MONSEEN_SEEINVIS;
  1573.      /* infravision */
  1574. -    if ((!mon->minvis || See_invisible) && see_with_infrared(mon))
  1575. +    if ((!minvisible(mon) || See_invisible) && see_with_infrared(mon))
  1576.          how_seen |= MONSEEN_INFRAVIS;
  1577.      /* telepathy */
  1578.      if (tp_sensemon(mon))
  1579. diff --git c/src/worn.c w/src/worn.c
  1580. index 1a966b7..05328b3 100644
  1581. --- c/src/worn.c
  1582. +++ w/src/worn.c
  1583. @@ -522,7 +522,7 @@ boolean racialexception;
  1584.          return; /* probably putting previous item on */
  1585.  
  1586.      /* Get a copy of monster's name before altering its visibility */
  1587. -    Strcpy(nambuf, See_invisible ? Monnam(mon) : mon_nam(mon));
  1588. +    Strcpy(nambuf, mon_nam(mon));
  1589.  
  1590.      old = which_armor(mon, flag);
  1591.      if (old && old->cursed)
  1592. @@ -640,7 +640,7 @@ outer_break:
  1593.      update_mon_intrinsics(mon, best, TRUE, creation);
  1594.      /* if couldn't see it but now can, or vice versa, */
  1595.      if (!creation && (unseen ^ !canseemon(mon))) {
  1596. -        if (mon->minvis && !See_invisible) {
  1597. +        if (minvisible(mon) && !See_invisible) {
  1598.              pline("Suddenly you cannot see %s.", nambuf);
  1599.              makeknown(best->otyp);
  1600.          } /* else if (!mon->minvis) pline("%s suddenly appears!",
  1601. diff --git c/src/zap.c w/src/zap.c
  1602. index a9350eb..ec6526a 100644
  1603. --- c/src/zap.c
  1604. +++ w/src/zap.c
  1605. @@ -3353,7 +3353,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
  1606.                     prepared for multiple hits so just get first one
  1607.                     that's either visible or could see its invisible
  1608.                     self.  [No tmp_at() cleanup is needed here.] */
  1609. -                if (!mtmp->minvis || perceives(mtmp->data))
  1610. +                if (!minvisible(mtmp) || perceives(mtmp->data))
  1611.                      return mtmp;
  1612.              } else if (weapon != ZAPPED_WAND) {
Add Comment
Please, Sign In to add comment