Source:NetHack 3.6.0/src/light.c

From NetHackWiki
(Redirected from Source:Light.c)
Jump to: navigation, search

Below is the full text to light.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/light.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	light.c	$NHDT-Date: 1446191876 2015/10/30 07:57:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
  2.  /* Copyright (c) Dean Luick, 1994                                       */
  3.  /* NetHack may be freely redistributed.  See license for details.       */
  4.  
  5.  #include "hack.h"
  6.  #include "lev.h" /* for checking save modes */
  7.  
  8.  /*
  9.   * Mobile light sources.
  10.   *
  11.   * This implementation minimizes memory at the expense of extra
  12.   * recalculations.
  13.   *
  14.   * Light sources are "things" that have a physical position and range.
  15.   * They have a type, which gives us information about them.  Currently
  16.   * they are only attached to objects and monsters.  Note well:  the
  17.   * polymorphed-player handling assumes that both youmonst.m_id and
  18.   * youmonst.mx will always remain 0.
  19.   *
  20.   * Light sources, like timers, either follow game play (RANGE_GLOBAL) or
  21.   * stay on a level (RANGE_LEVEL).  Light sources are unique by their
  22.   * (type, id) pair.  For light sources attached to objects, this id
  23.   * is a pointer to the object.
  24.   *
  25.   * The major working function is do_light_sources(). It is called
  26.   * when the vision system is recreating its "could see" array.  Here
  27.   * we add a flag (TEMP_LIT) to the array for all locations that are lit
  28.   * via a light source.  The bad part of this is that we have to
  29.   * re-calculate the LOS of each light source every time the vision
  30.   * system runs.  Even if the light sources and any topology (vision blocking
  31.   * positions) have not changed.  The good part is that no extra memory
  32.   * is used, plus we don't have to figure out how far the sources have moved,
  33.   * or if the topology has changed.
  34.   *
  35.   * The structure of the save/restore mechanism is amazingly similar to
  36.   * the timer save/restore.  This is because they both have the same
  37.   * principals of having pointers into objects that must be recalculated
  38.   * across saves and restores.
  39.   */
  40.  
  41.  /* flags */
  42.  #define LSF_SHOW 0x1        /* display the light source */
  43.  #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */
  44.  
  45.  static light_source *light_base = 0;
  46.  
  47.  STATIC_DCL void FDECL(write_ls, (int, light_source *));
  48.  STATIC_DCL int FDECL(maybe_write_ls, (int, int, BOOLEAN_P));
  49.  
  50.  /* imported from vision.c, for small circles */
  51.  extern char circle_data[];
  52.  extern char circle_start[];
  53.  

new_light_source

  1.  /* Create a new light source.  */
  2.  void
  3.  new_light_source(x, y, range, type, id)
  4.  xchar x, y;
  5.  int range, type;
  6.  anything *id;
  7.  {
  8.      light_source *ls;
  9.  
  10.      if (range > MAX_RADIUS || range < 1) {
  11.          impossible("new_light_source:  illegal range %d", range);
  12.          return;
  13.      }
  14.  
  15.      ls = (light_source *) alloc(sizeof(light_source));
  16.  
  17.      ls->next = light_base;
  18.      ls->x = x;
  19.      ls->y = y;
  20.      ls->range = range;
  21.      ls->type = type;
  22.      ls->id = *id;
  23.      ls->flags = 0;
  24.      light_base = ls;
  25.  
  26.      vision_full_recalc = 1; /* make the source show up */
  27.  }
  28.  

del_light_source

  1.  /*
  2.   * Delete a light source. This assumes only one light source is attached
  3.   * to an object at a time.
  4.   */
  5.  void
  6.  del_light_source(type, id)
  7.  int type;
  8.  anything *id;
  9.  {
  10.      light_source *curr, *prev;
  11.      anything tmp_id;
  12.  
  13.      tmp_id = zeroany;
  14.      /* need to be prepared for dealing a with light source which
  15.         has only been partially restored during a level change
  16.         (in particular: chameleon vs prot. from shape changers) */
  17.      switch (type) {
  18.      case LS_OBJECT:
  19.          tmp_id.a_uint = id->a_obj->o_id;
  20.          break;
  21.      case LS_MONSTER:
  22.          tmp_id.a_uint = id->a_monst->m_id;
  23.          break;
  24.      default:
  25.          tmp_id.a_uint = 0;
  26.          break;
  27.      }
  28.  
  29.      for (prev = 0, curr = light_base; curr; prev = curr, curr = curr->next) {
  30.          if (curr->type != type)
  31.              continue;
  32.          if (curr->id.a_obj
  33.              == ((curr->flags & LSF_NEEDS_FIXUP) ? tmp_id.a_obj : id->a_obj)) {
  34.              if (prev)
  35.                  prev->next = curr->next;
  36.              else
  37.                  light_base = curr->next;
  38.  
  39.              free((genericptr_t) curr);
  40.              vision_full_recalc = 1;
  41.              return;
  42.          }
  43.      }
  44.      impossible("del_light_source: not found type=%d, id=%s", type,
  45.                 fmt_ptr((genericptr_t) id->a_obj));
  46.  }
  47.  

do_light_sources

  1.  /* Mark locations that are temporarily lit via mobile light sources. */
  2.  void
  3.  do_light_sources(cs_rows)
  4.  char **cs_rows;
  5.  {
  6.      int x, y, min_x, max_x, max_y, offset;
  7.      char *limits;
  8.      short at_hero_range = 0;
  9.      light_source *ls;
  10.      char *row;
  11.  
  12.      for (ls = light_base; ls; ls = ls->next) {
  13.          ls->flags &= ~LSF_SHOW;
  14.  
  15.          /*
  16.           * Check for moved light sources.  It may be possible to
  17.           * save some effort if an object has not moved, but not in
  18.           * the current setup -- we need to recalculate for every
  19.           * vision recalc.
  20.           */
  21.          if (ls->type == LS_OBJECT) {
  22.              if (get_obj_location(ls->id.a_obj, &ls->x, &ls->y, 0))
  23.                  ls->flags |= LSF_SHOW;
  24.          } else if (ls->type == LS_MONSTER) {
  25.              if (get_mon_location(ls->id.a_monst, &ls->x, &ls->y, 0))
  26.                  ls->flags |= LSF_SHOW;
  27.          }
  28.  
  29.          /* minor optimization: don't bother with duplicate light sources */
  30.          /* at hero */
  31.          if (ls->x == u.ux && ls->y == u.uy) {
  32.              if (at_hero_range >= ls->range)
  33.                  ls->flags &= ~LSF_SHOW;
  34.              else
  35.                  at_hero_range = ls->range;
  36.          }
  37.  
  38.          if (ls->flags & LSF_SHOW) {
  39.              /*
  40.               * Walk the points in the circle and see if they are
  41.               * visible from the center.  If so, mark'em.
  42.               *
  43.               * Kevin's tests indicated that doing this brute-force
  44.               * method is faster for radius <= 3 (or so).
  45.               */
  46.              limits = circle_ptr(ls->range);
  47.              if ((max_y = (ls->y + ls->range)) >= ROWNO)
  48.                  max_y = ROWNO - 1;
  49.              if ((y = (ls->y - ls->range)) < 0)
  50.                  y = 0;
  51.              for (; y <= max_y; y++) {
  52.                  row = cs_rows[y];
  53.                  offset = limits[abs(y - ls->y)];
  54.                  if ((min_x = (ls->x - offset)) < 0)
  55.                      min_x = 0;
  56.                  if ((max_x = (ls->x + offset)) >= COLNO)
  57.                      max_x = COLNO - 1;
  58.  
  59.                  if (ls->x == u.ux && ls->y == u.uy) {
  60.                      /*
  61.                       * If the light source is located at the hero, then
  62.                       * we can use the COULD_SEE bits already calculated
  63.                       * by the vision system.  More importantly than
  64.                       * this optimization, is that it allows the vision
  65.                       * system to correct problems with clear_path().
  66.                       * The function clear_path() is a simple LOS
  67.                       * path checker that doesn't go out of its way
  68.                       * make things look "correct".  The vision system
  69.                       * does this.
  70.                       */
  71.                      for (x = min_x; x <= max_x; x++)
  72.                          if (row[x] & COULD_SEE)
  73.                              row[x] |= TEMP_LIT;
  74.                  } else {
  75.                      for (x = min_x; x <= max_x; x++)
  76.                          if ((ls->x == x && ls->y == y)
  77.                              || clear_path((int) ls->x, (int) ls->y, x, y))
  78.                              row[x] |= TEMP_LIT;
  79.                  }
  80.              }
  81.          }
  82.      }
  83.  }
  84.  

find_mid

  1.  /* (mon->mx == 0) implies migrating */
  2.  #define mon_is_local(mon) ((mon)->mx > 0)
  3.  
  4.  struct monst *
  5.  find_mid(nid, fmflags)
  6.  unsigned nid;
  7.  unsigned fmflags;
  8.  {
  9.      struct monst *mtmp;
  10.  
  11.      if (!nid)
  12.          return &youmonst;
  13.      if (fmflags & FM_FMON)
  14.          for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  15.              if (!DEADMONSTER(mtmp) && mtmp->m_id == nid)
  16.                  return mtmp;
  17.      if (fmflags & FM_MIGRATE)
  18.          for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
  19.              if (mtmp->m_id == nid)
  20.                  return mtmp;
  21.      if (fmflags & FM_MYDOGS)
  22.          for (mtmp = mydogs; mtmp; mtmp = mtmp->nmon)
  23.              if (mtmp->m_id == nid)
  24.                  return mtmp;
  25.      return (struct monst *) 0;
  26.  }
  27.  

save_light_sources

  1.  /* Save all light sources of the given range. */
  2.  void
  3.  save_light_sources(fd, mode, range)
  4.  int fd, mode, range;
  5.  {
  6.      int count, actual, is_global;
  7.      light_source **prev, *curr;
  8.  
  9.      if (perform_bwrite(mode)) {
  10.          count = maybe_write_ls(fd, range, FALSE);
  11.          bwrite(fd, (genericptr_t) &count, sizeof count);
  12.          actual = maybe_write_ls(fd, range, TRUE);
  13.          if (actual != count)
  14.              panic("counted %d light sources, wrote %d! [range=%d]", count,
  15.                    actual, range);
  16.      }
  17.  
  18.      if (release_data(mode)) {
  19.          for (prev = &light_base; (curr = *prev) != 0;) {
  20.              if (!curr->id.a_monst) {
  21.                  impossible("save_light_sources: no id! [range=%d]", range);
  22.                  is_global = 0;
  23.              } else
  24.                  switch (curr->type) {
  25.                  case LS_OBJECT:
  26.                      is_global = !obj_is_local(curr->id.a_obj);
  27.                      break;
  28.                  case LS_MONSTER:
  29.                      is_global = !mon_is_local(curr->id.a_monst);
  30.                      break;
  31.                  default:
  32.                      is_global = 0;
  33.                      impossible("save_light_sources: bad type (%d) [range=%d]",
  34.                                 curr->type, range);
  35.                      break;
  36.                  }
  37.              /* if global and not doing local, or vice versa, remove it */
  38.              if (is_global ^ (range == RANGE_LEVEL)) {
  39.                  *prev = curr->next;
  40.                  free((genericptr_t) curr);
  41.              } else {
  42.                  prev = &(*prev)->next;
  43.              }
  44.          }
  45.      }
  46.  }
  47.  

restore_light_sources

  1.  /*
  2.   * Pull in the structures from disk, but don't recalculate the object
  3.   * pointers.
  4.   */
  5.  void
  6.  restore_light_sources(fd)
  7.  int fd;
  8.  {
  9.      int count;
  10.      light_source *ls;
  11.  
  12.      /* restore elements */
  13.      mread(fd, (genericptr_t) &count, sizeof count);
  14.  
  15.      while (count-- > 0) {
  16.          ls = (light_source *) alloc(sizeof(light_source));
  17.          mread(fd, (genericptr_t) ls, sizeof(light_source));
  18.          ls->next = light_base;
  19.          light_base = ls;
  20.      }
  21.  }
  22.  

relink_light_sources

  1.  /* Relink all lights that are so marked. */
  2.  void
  3.  relink_light_sources(ghostly)
  4.  boolean ghostly;
  5.  {
  6.      char which;
  7.      unsigned nid;
  8.      light_source *ls;
  9.  
  10.      for (ls = light_base; ls; ls = ls->next) {
  11.          if (ls->flags & LSF_NEEDS_FIXUP) {
  12.              if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
  13.                  if (ghostly) {
  14.                      if (!lookup_id_mapping(ls->id.a_uint, &nid))
  15.                          impossible("relink_light_sources: no id mapping");
  16.                  } else
  17.                      nid = ls->id.a_uint;
  18.                  if (ls->type == LS_OBJECT) {
  19.                      which = 'o';
  20.                      ls->id.a_obj = find_oid(nid);
  21.                  } else {
  22.                      which = 'm';
  23.                      ls->id.a_monst = find_mid(nid, FM_EVERYWHERE);
  24.                  }
  25.                  if (!ls->id.a_monst)
  26.                      impossible("relink_light_sources: cant find %c_id %d",
  27.                                 which, nid);
  28.              } else
  29.                  impossible("relink_light_sources: bad type (%d)", ls->type);
  30.  
  31.              ls->flags &= ~LSF_NEEDS_FIXUP;
  32.          }
  33.      }
  34.  }
  35.  

maybe_write_ls

  1.  /*
  2.   * Part of the light source save routine.  Count up the number of light
  3.   * sources that would be written.  If write_it is true, actually write
  4.   * the light source out.
  5.   */
  6.  STATIC_OVL int
  7.  maybe_write_ls(fd, range, write_it)
  8.  int fd, range;
  9.  boolean write_it;
  10.  {
  11.      int count = 0, is_global;
  12.      light_source *ls;
  13.  
  14.      for (ls = light_base; ls; ls = ls->next) {
  15.          if (!ls->id.a_monst) {
  16.              impossible("maybe_write_ls: no id! [range=%d]", range);
  17.              continue;
  18.          }
  19.          switch (ls->type) {
  20.          case LS_OBJECT:
  21.              is_global = !obj_is_local(ls->id.a_obj);
  22.              break;
  23.          case LS_MONSTER:
  24.              is_global = !mon_is_local(ls->id.a_monst);
  25.              break;
  26.          default:
  27.              is_global = 0;
  28.              impossible("maybe_write_ls: bad type (%d) [range=%d]", ls->type,
  29.                         range);
  30.              break;
  31.          }
  32.          /* if global and not doing local, or vice versa, count it */
  33.          if (is_global ^ (range == RANGE_LEVEL)) {
  34.              count++;
  35.              if (write_it)
  36.                  write_ls(fd, ls);
  37.          }
  38.      }
  39.  
  40.      return count;
  41.  }
  42.  

light_sources_sanity_check

  1.  void
  2.  light_sources_sanity_check()
  3.  {
  4.      light_source *ls;
  5.      struct monst *mtmp;
  6.      struct obj *otmp;
  7.      unsigned int auint;
  8.  
  9.      for (ls = light_base; ls; ls = ls->next) {
  10.          if (!ls->id.a_monst)
  11.              panic("insane light source: no id!");
  12.          if (ls->type == LS_OBJECT) {
  13.              otmp = (struct obj *) ls->id.a_obj;
  14.              auint = otmp->o_id;
  15.              if (find_oid(auint) != otmp)
  16.                  panic("insane light source: can't find obj #%u!", auint);
  17.          } else if (ls->type == LS_MONSTER) {
  18.              mtmp = (struct monst *) ls->id.a_monst;
  19.              auint = mtmp->m_id;
  20.              if (find_mid(auint, FM_EVERYWHERE) != mtmp)
  21.                  panic("insane light source: can't find mon #%u!", auint);
  22.          } else {
  23.              panic("insane light source: bad ls type %d", ls->type);
  24.          }
  25.      }
  26.  }
  27.  

write_ls

  1.  /* Write a light source structure to disk. */
  2.  STATIC_OVL void
  3.  write_ls(fd, ls)
  4.  int fd;
  5.  light_source *ls;
  6.  {
  7.      anything arg_save;
  8.      struct obj *otmp;
  9.      struct monst *mtmp;
  10.  
  11.      if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
  12.          if (ls->flags & LSF_NEEDS_FIXUP) {
  13.              bwrite(fd, (genericptr_t) ls, sizeof(light_source));
  14.          } else {
  15.              /* replace object pointer with id for write, then put back */
  16.              arg_save = ls->id;
  17.              if (ls->type == LS_OBJECT) {
  18.                  otmp = ls->id.a_obj;
  19.                  ls->id = zeroany;
  20.                  ls->id.a_uint = otmp->o_id;
  21.                  if (find_oid((unsigned) ls->id.a_uint) != otmp)
  22.                      impossible("write_ls: can't find obj #%u!",
  23.                                 ls->id.a_uint);
  24.              } else { /* ls->type == LS_MONSTER */
  25.                  mtmp = (struct monst *) ls->id.a_monst;
  26.                  ls->id = zeroany;
  27.                  ls->id.a_uint = mtmp->m_id;
  28.                  if (find_mid((unsigned) ls->id.a_uint, FM_EVERYWHERE) != mtmp)
  29.                      impossible("write_ls: can't find mon #%u!",
  30.                                 ls->id.a_uint);
  31.              }
  32.              ls->flags |= LSF_NEEDS_FIXUP;
  33.              bwrite(fd, (genericptr_t) ls, sizeof(light_source));
  34.              ls->id = arg_save;
  35.              ls->flags &= ~LSF_NEEDS_FIXUP;
  36.          }
  37.      } else {
  38.          impossible("write_ls: bad type (%d)", ls->type);
  39.      }
  40.  }
  41.  

obj_move_light_source

  1.  /* Change light source's ID from src to dest. */
  2.  void
  3.  obj_move_light_source(src, dest)
  4.  struct obj *src, *dest;
  5.  {
  6.      light_source *ls;
  7.  
  8.      for (ls = light_base; ls; ls = ls->next)
  9.          if (ls->type == LS_OBJECT && ls->id.a_obj == src)
  10.              ls->id.a_obj = dest;
  11.      src->lamplit = 0;
  12.      dest->lamplit = 1;
  13.  }
  14.  

any_light_source

  1.  /* return true if there exist any light sources */
  2.  boolean
  3.  any_light_source()
  4.  {
  5.      return (boolean) (light_base != (light_source *) 0);
  6.  }
  7.  

snuff_light_source

  1.  /*
  2.   * Snuff an object light source if at (x,y).  This currently works
  3.   * only for burning light sources.
  4.   */
  5.  void
  6.  snuff_light_source(x, y)
  7.  int x, y;
  8.  {
  9.      light_source *ls;
  10.      struct obj *obj;
  11.  
  12.      for (ls = light_base; ls; ls = ls->next)
  13.          /*
  14.           * Is this position check valid??? Can I assume that the positions
  15.           * will always be correct because the objects would have been
  16.           * updated with the last vision update?  [Is that recent enough???]
  17.           */
  18.          if (ls->type == LS_OBJECT && ls->x == x && ls->y == y) {
  19.              obj = ls->id.a_obj;
  20.              if (obj_is_burning(obj)) {
  21.                  /* The only way to snuff Sunsword is to unwield it.  Darkness
  22.                   * scrolls won't affect it.  (If we got here because it was
  23.                   * dropped or thrown inside a monster, this won't matter
  24.                   * anyway because it will go out when dropped.)
  25.                   */
  26.                  if (artifact_light(obj))
  27.                      continue;
  28.                  end_burn(obj, obj->otyp != MAGIC_LAMP);
  29.                  /*
  30.                   * The current ls element has just been removed (and
  31.                   * ls->next is now invalid).  Return assuming that there
  32.                   * is only one light source attached to each object.
  33.                   */
  34.                  return;
  35.              }
  36.          }
  37.  }
  38.  

obj_sheds_light

  1.  /* Return TRUE if object sheds any light at all. */
  2.  boolean
  3.  obj_sheds_light(obj)
  4.  struct obj *obj;
  5.  {
  6.      /* so far, only burning objects shed light */
  7.      return obj_is_burning(obj);
  8.  }
  9.  

obj_is_burning

  1.  /* Return TRUE if sheds light AND will be snuffed by end_burn(). */
  2.  boolean
  3.  obj_is_burning(obj)
  4.  struct obj *obj;
  5.  {
  6.      return (boolean) (obj->lamplit && (obj->otyp == MAGIC_LAMP
  7.                                         || ignitable(obj)
  8.                                         || artifact_light(obj)));
  9.  }
  10.  

obj_split_light_source

  1.  /* copy the light source(s) attached to src, and attach it/them to dest */
  2.  void
  3.  obj_split_light_source(src, dest)
  4.  struct obj *src, *dest;
  5.  {
  6.      light_source *ls, *new_ls;
  7.  
  8.      for (ls = light_base; ls; ls = ls->next)
  9.          if (ls->type == LS_OBJECT && ls->id.a_obj == src) {
  10.              /*
  11.               * Insert the new source at beginning of list.  This will
  12.               * never interfere us walking down the list - we are already
  13.               * past the insertion point.
  14.               */
  15.              new_ls = (light_source *) alloc(sizeof(light_source));
  16.              *new_ls = *ls;
  17.              if (Is_candle(src)) {
  18.                  /* split candles may emit less light than original group */
  19.                  ls->range = candle_light_range(src);
  20.                  new_ls->range = candle_light_range(dest);
  21.                  vision_full_recalc = 1; /* in case range changed */
  22.              }
  23.              new_ls->id.a_obj = dest;
  24.              new_ls->next = light_base;
  25.              light_base = new_ls;
  26.              dest->lamplit = 1; /* now an active light source */
  27.          }
  28.  }
  29.  

obj_merge_light_sources

  1.  /* light source `src' has been folded into light source `dest';
  2.     used for merging lit candles and adding candle(s) to lit candelabrum */
  3.  void
  4.  obj_merge_light_sources(src, dest)
  5.  struct obj *src, *dest;
  6.  {
  7.      light_source *ls;
  8.  
  9.      /* src == dest implies adding to candelabrum */
  10.      if (src != dest)
  11.          end_burn(src, TRUE); /* extinguish candles */
  12.  
  13.      for (ls = light_base; ls; ls = ls->next)
  14.          if (ls->type == LS_OBJECT && ls->id.a_obj == dest) {
  15.              ls->range = candle_light_range(dest);
  16.              vision_full_recalc = 1; /* in case range changed */
  17.              break;
  18.          }
  19.  }
  20.  

obj_adjust_light_radius

  1.  /* light source `obj' is being made brighter or dimmer */
  2.  void
  3.  obj_adjust_light_radius(obj, new_radius)
  4.  struct obj *obj;
  5.  int new_radius;
  6.  {
  7.      light_source *ls;
  8.  
  9.      for (ls = light_base; ls; ls = ls->next)
  10.          if (ls->type == LS_OBJECT && ls->id.a_obj == obj) {
  11.              if (new_radius != ls->range)
  12.                  vision_full_recalc = 1;
  13.              ls->range = new_radius;
  14.              return;
  15.          }
  16.      impossible("obj_adjust_light_radius: can't find %s", xname(obj));
  17.  }
  18.  

candle_light_range

  1.  /* Candlelight is proportional to the number of candles;
  2.     minimum range is 2 rather than 1 for playability. */
  3.  int
  4.  candle_light_range(obj)
  5.  struct obj *obj;
  6.  {
  7.      int radius;
  8.  
  9.      if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
  10.          /*
  11.           *      The special candelabrum emits more light than the
  12.           *      corresponding number of candles would.
  13.           *       1..3 candles, range 2 (minimum range);
  14.           *       4..6 candles, range 3 (normal lamp range);
  15.           *          7 candles, range 4 (bright).
  16.           */
  17.          radius = (obj->spe < 4) ? 2 : (obj->spe < 7) ? 3 : 4;
  18.      } else if (Is_candle(obj)) {
  19.          /*
  20.           *      Range is incremented by powers of 7 so that it will take
  21.           *      wizard mode quantities of candles to get more light than
  22.           *      from a lamp, without imposing an arbitrary limit.
  23.           *       1..6   candles, range 2;
  24.           *       7..48  candles, range 3;
  25.           *      49..342 candles, range 4; &c.
  26.           */
  27.          long n = obj->quan;
  28.  
  29.          radius = 1; /* always incremented at least once */
  30.          do {
  31.              radius++;
  32.              n /= 7L;
  33.          } while (n > 0L);
  34.      } else {
  35.          /* we're only called for lit candelabrum or candles */
  36.          /* impossible("candlelight for %d?", obj->otyp); */
  37.          radius = 3; /* lamp's value */
  38.      }
  39.      return radius;
  40.  }
  41.  

arti_light_radius

  1.  /* light emitting artifact's range depends upon its curse/bless state */
  2.  int
  3.  arti_light_radius(obj)
  4.  struct obj *obj;
  5.  {
  6.      /*
  7.       * Used by begin_burn() when setting up a new light source
  8.       * (obj->lamplit will already be set by this point) and
  9.       * also by bless()/unbless()/uncurse()/curse() to decide
  10.       * whether to call obj_adjust_light_radius().
  11.       */
  12.  
  13.      /* sanity check [simplifies usage by bless()/curse()/&c] */
  14.      if (!obj->lamplit || !artifact_light(obj))
  15.          return 0;
  16.  
  17.      /* cursed radius of 1 is not noticeable for an item that's
  18.         carried by the hero but is if it's carried by a monster
  19.         or left lit on the floor (not applicable for Sunsword) */
  20.      return (obj->blessed ? 3 : !obj->cursed ? 2 : 1);
  21.  }
  22.  

arti_light_description

  1.  /* adverb describing lit artifact's light; depends on curse/bless state */
  2.  const char *
  3.  arti_light_description(obj)
  4.  struct obj *obj;
  5.  {
  6.      switch (arti_light_radius(obj)) {
  7.      case 3:
  8.          return "brilliantly"; /* blessed */
  9.      case 2:
  10.          return "brightly"; /* uncursed */
  11.      case 1:
  12.          return "dimly"; /* cursed */
  13.      default:
  14.          break;
  15.      }
  16.      return "strangely";
  17.  }
  18.  

wiz_light_sources

  1.  int
  2.  wiz_light_sources()
  3.  {
  4.      winid win;
  5.      char buf[BUFSZ];
  6.      light_source *ls;
  7.  
  8.      win = create_nhwindow(NHW_MENU); /* corner text window */
  9.      if (win == WIN_ERR)
  10.          return 0;
  11.  
  12.      Sprintf(buf, "Mobile light sources: hero @ (%2d,%2d)", u.ux, u.uy);
  13.      putstr(win, 0, buf);
  14.      putstr(win, 0, "");
  15.  
  16.      if (light_base) {
  17.          putstr(win, 0, "location range flags  type    id");
  18.          putstr(win, 0, "-------- ----- ------ ----  -------");
  19.          for (ls = light_base; ls; ls = ls->next) {
  20.              Sprintf(buf, "  %2d,%2d   %2d   0x%04x  %s  %s", ls->x, ls->y,
  21.                      ls->range, ls->flags,
  22.                      (ls->type == LS_OBJECT
  23.                         ? "obj"
  24.                         : ls->type == LS_MONSTER
  25.                            ? (mon_is_local(ls->id.a_monst)
  26.                               ? "mon"
  27.                               : (ls->id.a_monst == &youmonst)
  28.                                  ? "you"
  29.                                  /* migrating monster */
  30.                                  : "<m>")
  31.                            : "???"),
  32.                      fmt_ptr(ls->id.a_void));
  33.              putstr(win, 0, buf);
  34.          }
  35.      } else
  36.          putstr(win, 0, "<none>");
  37.  
  38.      display_nhwindow(win, FALSE);
  39.      destroy_nhwindow(win);
  40.  
  41.      return 0;
  42.  }
  43.  
  44.  /*light.c*/