text: /* NetHack 3.7	display.h	$NHDT-Date: 1605927391 2020/11/21 02:56:31 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.48 $ */
  /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
  /* and Dave Cohrs, 1990.                                          */
  /* NetHack may be freely redistributed.  See license for details. */
  
  #ifndef DISPLAY_H
  #define DISPLAY_H
  
  #ifndef VISION_H
  #include "vision.h"
  #endif
  #ifndef MONDATA_H
  #include "mondata.h" /* for mindless() */
  #endif
  
  /*
   * vobj_at()
   *
   * Returns the head of the list of objects that the player can see
   * at location (x,y).
   */
  #define vobj_at(x, y) (g.level.objects[x][y])
  
  /*
   * sensemon()
   *
   * Returns true if the hero can sense the given monster.  This includes
   * monsters that are hiding or mimicing other monsters.
   *
   * [3.7] Note: the map doesn't display any monsters when hero is swallowed
   * (or display non-adjacent, non-submerged ones when hero is underwater),
   * so treat those situations as blocking telepathy, detection, and warning
   * even though conceptually they shouldn't do so.
   */
  #define tp_sensemon(mon) \
      (/* The hero can always sense a monster IF:        */  \
       /* 1. the monster has a brain to sense            */  \
       (!mindless(mon->data))                                \
       /* AND     2a. hero is blind and telepathic       */  \
        && ((Blind && Blind_telepat)                         \
            /* OR 2b. hero is using a telepathy inducing */  \
            /*        object and in range                */  \
            || (Unblind_telepat                              \
                && (distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM)))))
  /* organized to perform cheaper tests first;
     is_pool() vs is_pool_or_lava(): hero who is underwater can see adjacent
     lava, but presumeably any monster there is on top so not sensed */
  #define sensemon(mon) \
      (   (!u.uswallow || (mon) == u.ustuck)                                 \
       && (!Underwater || (distu((mon)->mx, (mon)->my) <= 2                  \
                           && is_pool((mon)->mx, (mon)->my)))                \
       && (Detect_monsters || tp_sensemon(mon) || MATCH_WARN_OF_MON(mon))   )
  
  /*
   * mon_warning() is used to warn of any dangerous monsters in your
   * vicinity, and a glyph representing the warning level is displayed.
   */
  #define mon_warning(mon)                                                 \
      (Warning && !(mon)->mpeaceful && (distu((mon)->mx, (mon)->my) < 100) \
       && (((int) ((mon)->m_lev / 4)) >= g.context.warnlevel))
  
  /*
   * mon_visible()
   *
   * Returns true if the hero can see the monster.  It is assumed that the
   * hero can physically see the location of the monster.  The function
   * vobj_at() returns a pointer to an object that the hero can see there.
   * Infravision is not taken into account.
   *
   * Note:  not reliable for concealed mimics.  They don't have
   * 'mon->mundetected' set even when mimicking objects or furniture.
   * [Fixing this with a pair of mon->m_ap_type checks here (via either
   * 'typ!=object && typ!=furniture' or 'typ==nothing || typ==monster')
   * will require reviewing every instance of mon_visible(), canseemon(),
   * canspotmon(), is_safemon() and perhaps others.  Fixing it by setting
   * mon->mundetected when concealed would be better but also require
   * reviewing all those instances and also existing mundetected instances.]
   */
  #if 0
  #define mon_visible(mon) \
      (/* The hero can see the monster IF the monster                     */ \
       (!mon->minvis || See_invisible)  /*     1. is not invisible        */ \
       && !mon->mundetected             /* AND 2. not an undetected hider */ \
       && !(mon->mburied || u.uburied)) /* AND 3. neither you nor it is buried */
  #else   /* without 'mburied' and 'uburied' */
  #define mon_visible(mon) \
      (/* The hero can see the monster IF the monster                     */ \
       (!mon->minvis || See_invisible)  /*     1. is not invisible        */ \
       && !mon->mundetected)            /* AND 2. not an undetected hider */
  #endif
  
  /*
   * see_with_infrared()
   *
   * This function is true if the player can see a monster using infravision.
   * The caller must check for invisibility (invisible monsters are also
   * invisible to infravision), because this is usually called from within
   * canseemon() or canspotmon() which already check that.
   */
  #define see_with_infrared(mon)                        \
      (!Blind && Infravision && mon && infravisible(mon->data) \
       && couldsee(mon->mx, mon->my))
  
  /*
   * canseemon()
   *
   * This is the globally used canseemon().  It is not called within the display
   * routines.  Like mon_visible(), but it checks to see if the hero sees the
   * location instead of assuming it.  (And also considers worms.)
   */
  #define canseemon(mon)                                                    \
      ((mon->wormno ? worm_known(mon)                                       \
                    : (cansee(mon->mx, mon->my) || see_with_infrared(mon))) \
       && mon_visible(mon))
  
  /*
   * canspotmon(mon)
   *
   * This function checks whether you can either see a monster or sense it by
   * telepathy, and is what you usually call for monsters about which nothing is
   * known.
   */
  #define canspotmon(mon) (canseemon(mon) || sensemon(mon))
  
  /* knowninvisible(mon)
   * This one checks to see if you know a monster is both there and invisible.
   * 1) If you can see the monster and have see invisible, it is assumed the
   * monster is transparent, but visible in some manner.  (Earlier versions of
   * Nethack were really inconsistent on this.)
   * 2) If you can't see the monster, but can see its location and you have
   * telepathy that works when you can see, you can tell that there is a
   * creature in an apparently empty spot.
   * Infravision is not relevant; we assume that invisible monsters are also
   * invisible to infravision.
   */
  #define knowninvisible(mon)                                               \
      (mtmp->minvis                                                         \
       && ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) \
           || (!Blind && (HTelepat & ~INTRINSIC)                            \
               && distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM))))
  
  /*
   * is_safemon(mon)
   *
   * A special case check used in attack() and domove().  Placing the
   * definition here is convenient.  No longer limited to pets.
   */
  #define is_safemon(mon) \
      (flags.safe_dog && (mon) && (mon)->mpeaceful && canspotmon(mon)     \
       && !Confusion && !Hallucination && !Stunned)
  
  /*
   * canseeself()
   * senseself()
   * canspotself()
   *
   * This returns true if the hero can see her/himself.
   *
   * Sensing yourself by touch is treated as seeing yourself, even if
   * unable to see.  So when blind, being invisible won't affect your
   * self-perception, and when swallowed, the enclosing monster touches.
   */
  #define canseeself() (Blind || u.uswallow || (!Invisible && !u.uundetected))
  #define senseself() (Unblind_telepat || Detect_monsters)
  #define canspotself() (canseeself() || senseself())
  
  /*
   * random_monster()
   * random_object()
   *
   * Respectively return a random monster or object.
   */
  #define random_monster(rng) rng(NUMMONS)
  #define random_object(rng) (rng(NUM_OBJECTS - 1) + 1)
  
  /*
   * what_obj()
   * what_mon()
   *
   * If hallucinating, choose a random object/monster, otherwise, use the one
   * given. Use the given rng to handle hallucination.
   */
  #define what_obj(obj, rng) (Hallucination ? random_object(rng) : obj)
  #define what_mon(mon, rng) (Hallucination ? random_monster(rng) : mon)
  
  /*
   * newsym_rn2
   *
   * An appropriate random number generator for use with newsym(), when
   * randomness is needed there. This is currently hardcoded as
   * rn2_on_display_rng, but is futureproofed for cases where we might
   * want to prevent display-random objects entering the character's
   * memory (this isn't important at present but may be if we need
   * reproducible gameplay for some reason).
   */
  #define newsym_rn2 rn2_on_display_rng
  
  /*
   * covers_objects()
   * covers_traps()
   *
   * These routines are true if what is really at the given location will
   * "cover" any objects or traps that might be there.
   */
  #define covers_objects(xx, yy) \
      ((is_pool(xx, yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL))
  
  #define covers_traps(xx, yy) covers_objects(xx, yy)
  
  /*
   * tmp_at() control calls.
   */
  #define DISP_BEAM    (-1) /* Keep all glyphs showing & clean up at end. */
  #define DISP_ALL     (-2) /* Like beam, but still displayed if not visible. */
  #define DISP_TETHER  (-3) /* Like beam, but tether glyph differs from final */
  #define DISP_FLASH   (-4) /* Clean up each glyph before displaying new one. */
  #define DISP_ALWAYS  (-5) /* Like flash, but still displayed if not visible. */
  #define DISP_CHANGE  (-6) /* Change glyph. */
  #define DISP_END     (-7) /* Clean up. */
  #define DISP_FREEMEM (-8) /* Free all memory during exit only. */
  
  /* Total number of cmap indices in the shield_static[] array. */
  #define SHIELD_COUNT 21
  #define BACKTRACK (-1)    /* flag for DISP_END to display each prior location */
  
  /*
   * display_self()
   *
   * Display the hero.  It is assumed that all checks necessary to determine
   * _if_ the hero can be seen have already been done.
   */
  #define maybe_display_usteed(otherwise_self)                 \
      ((u.usteed && mon_visible(u.usteed))                     \
           ? ridden_mon_to_glyph(u.usteed, rn2_on_display_rng) \
           : (otherwise_self))
  
  #define display_self() \
      show_glyph(u.ux, u.uy, maybe_display_usteed(                        \
          ((int) U_AP_TYPE == M_AP_NOTHING)                               \
          ? hero_glyph                                                    \
          : ((int) U_AP_TYPE == M_AP_FURNITURE)                           \
            ? cmap_to_glyph((int) g.youmonst.mappearance)                 \
            : ((int) U_AP_TYPE == M_AP_OBJECT)                            \
              ? objnum_to_glyph((int) g.youmonst.mappearance)             \
              /* else U_AP_TYPE == M_AP_MONSTER */                        \
              : monnum_to_glyph((int) g.youmonst.mappearance, Ugender)))
  
  /*
   * NetHack glyphs
   *
   * A glyph is an abstraction that represents a _unique_ monster, object,
   * dungeon part, or effect.  The uniqueness is important.  For example,
   * It is not enough to have four (one for each "direction") zap beam glyphs,
   * we need a set of four for each beam type.  Why go to so much trouble?
   * Because it is possible that any given window dependent display driver
   * [print_glyph()] can produce something different for each type of glyph.
   * That is, a beam of cold and a beam of fire would not only be different
   * colors, but would also be represented by different symbols.
   */
  
  
  #include "color.h"
  /* 3.6.3: poison gas zap used to be yellow and acid zap was green,
     which conflicted with the corresponding dragon colors */
  enum zap_colors {
      zap_color_missile    = HI_ZAP,
      zap_color_fire       = CLR_ORANGE,
      zap_color_frost      = CLR_WHITE,
      zap_color_sleep      = HI_ZAP,
      zap_color_death      = CLR_BLACK,
      zap_color_lightning  = CLR_WHITE,
      zap_color_poison_gas = CLR_GREEN,
      zap_color_acid       = CLR_YELLOW
  };
  
  enum altar_colors {
      altar_color_unaligned = CLR_RED,
  #if defined(USE_GENERAL_ALTAR_COLORS)
          /* On OSX with TERM=xterm-color256 these render as
           *  white -> tty: gray, curses: ok
           *  gray  -> both tty and curses: black
           *  black -> both tty and curses: blue
           *  red   -> both tty and curses: ok.
           * Since the colors have specific associations (with the
           * unicorns matched with each alignment), we shouldn't use
           * scrambled colors and we don't have sufficient information
           * to handle platform-specific color variations.
           */
      altar_color_chaotic = CLR_BLACK,
      altar_color_neutral = CLR_GRAY,
      altar_color_lawful  = CLR_WHITE,
  #else
      altar_color_chaotic = CLR_GRAY,
      altar_color_neutral = CLR_GRAY,
      altar_color_lawful  = CLR_GRAY,
  #endif
      altar_color_other = CLR_BRIGHT_MAGENTA,
  };
  
  /* types of explosions */
  enum explosion_types {
      EXPL_DARK = 0,
      EXPL_NOXIOUS = 1,
      EXPL_MUDDY = 2,
      EXPL_WET = 3,
      EXPL_MAGICAL = 4,
      EXPL_FIERY = 5,
      EXPL_FROSTY = 6,
      EXPL_MAX = 7
  };
  
  /* above plus this redundant? */
  enum expl_types {
      expl_dark,
      expl_noxious,
      expl_muddy,
      expl_wet,
      expl_magical,
      expl_fiery,
      expl_frosty,
  };
  
  enum explode_colors {
      explode_color_dark = CLR_BLACK,
      explode_color_noxious = CLR_GREEN,
      explode_color_muddy = CLR_BROWN,
      explode_color_wet = CLR_BLUE,
      explode_color_magical = CLR_MAGENTA,
      explode_color_fiery = CLR_ORANGE,
      explode_color_frosty = CLR_WHITE
  };
  enum altar_types {
      altar_unaligned,
      altar_chaotic,
      altar_neutral,
      altar_lawful,
      altar_other
  };
  enum level_walls  { main_walls, mines_walls, gehennom_walls,
                      knox_walls, sokoban_walls };
  enum { GM_FLAGS, GM_TTYCHAR, GM_COLOR, NUM_GLYPHMOD }; /* glyphmod entries */
  enum glyphmap_change_triggers { gm_nochange, gm_newgame, gm_levelchange,
                                  gm_optionchange, gm_symchange,
                                  gm_accessibility_change };
  #define NUM_ZAP 8 /* number of zap beam types */
  
  /*
   * Glyphs are grouped for easy accessibility:
   *
   * male monsters    Represents all the wild (not tame) male monsters.
   *                  Count: NUMMONS.
   *
   * female monsters  Represents all the wild (not tame) female monsters.
   *                  Count: NUMMONS.
   *
   * male pets        Represents all of the male tame monsters.
   *                  Count: NUMMONS.
   *
   * female pets      Represents all of the female tame monsters.
   *                  Count: NUMMONS.
   *
   * invisible        Invisible monster placeholder.
   *                  Count: 1.
   *
   * detect (male)    Represents all detected male monsters.
   *                  Count: NUMMONS.
   *
   * detect (female)  Represents all detected female monsters.
   *                  Count: NUMMONS.
   *
   * corpse           One for each monster (male/female not differentiated).
   *                  Count: NUMMONS.
   *
   * ridden (male)    Represents all male monsters being ridden.
   *                  Count: NUMMONS
   *
   * ridden (female)  Represents all female monsters being ridden.
   *                  Count: NUMMONS
   *
   * object           One for each object.
   *                  Count: NUM_OBJECTS
   *
   * Stone            Stone
   *                  Count: 1
   *
   * main walls       level walls (main)
   *                  Count: (S_trwall - S_vwall) + 1 = 11
   *
   * mines walls      level walls (mines)
   *                  Count: (S_trwall - S_vwall) + 1 = 11
   *
   * gehennom walls   level walls (gehennom)
   *                  Count: (S_trwall - S_vwall) + 1 = 11
   *
   * knox walls       level walls (knox)
   *                  Count: (S_trwall - S_vwall) + 1 = 11
   *
   * sokoban walls    level walls (sokoban)
   *                  Count: (S_trwall - S_vwall) + 1 = 11
   *
   * cmap A           S_ndoor through S_brdnladder
   *                  Count: (S_brdnladder - S_ndoor) + 1 = 19
   *
   * Altars           Altar (unaligned, chaotic, neutral, lawful, other)
   *                  Count: 5
   *
   * cmap B           S_grave through S_vibrating_square
   *                  Count: (S_vibrating_square - S_grave) + 1 = 37
   *
   * zap beams        set of four (there are four directions) HI_ZAP.
   *                  Count: 4 * NUM_ZAP
   *
   * cmap C           S_digbeam through S_goodpos
   *                  Count: (S_goodpos - S_digbeam) + 1 = 10
   *
   * swallow          A set of eight for each monster.  The eight positions
   *                  represent those surrounding the hero.  The monster
   *                  number is shifted over 3 positions and the swallow
   *                  position is stored in the lower three bits.
   *                  Count: NUMMONS << 3
   *
   * dark explosions        A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * noxious explosions     A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * muddy explosions       A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * wet explosions         A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * magical explosions     A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * fiery explosions       A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * frosty explosions      A set of nine.
   *                        Count: MAXEXPCHAR
   *
   * warning                A set of six representing the different warning levels.
   *                        Count: 6
   *
   * statues (male)         One for each male monster.
   *                        Count: NUMMONS
   *
   * statues (female)       One for each female mo nster.
   *                        Count: NUMMONS
   *
   * objects piletop        Represents the top of a pile as well as
   *                        the object.
   *                        Count: NUM_OBJECTS
   *
   * bodies piletop         Represents the top of a pile as well as
   *                        the object, corpse in this case.
   *                        Count: NUMMONS
   *
   * male statues piletop   Represents the top of a pile as well as
   *                        the statue of a male monster.
   *                        Count: NUMMONS
   *
   * female statues piletop Represents the top of a pile as well as
   *                        the statue of a female monster.
   *                        Count: NUMMONS
   *
   * unexplored             One for unexplored areas of the map
   * nothing                Nothing but background
   *
   * The following are offsets used to convert to and from a glyph.
   */
  
  enum glyph_offsets {
      GLYPH_MON_OFF = 0,
      GLYPH_MON_MALE_OFF = (GLYPH_MON_OFF),
      GLYPH_MON_FEM_OFF = (NUMMONS + GLYPH_MON_MALE_OFF),
      GLYPH_PET_OFF = (NUMMONS + GLYPH_MON_FEM_OFF),
      GLYPH_PET_MALE_OFF = (GLYPH_PET_OFF),
      GLYPH_PET_FEM_OFF = (NUMMONS + GLYPH_PET_MALE_OFF),
      GLYPH_INVIS_OFF = (NUMMONS + GLYPH_PET_FEM_OFF),
      GLYPH_DETECT_OFF = (1 + GLYPH_INVIS_OFF),
      GLYPH_DETECT_MALE_OFF = (GLYPH_DETECT_OFF),
      GLYPH_DETECT_FEM_OFF = (NUMMONS + GLYPH_DETECT_MALE_OFF),
      GLYPH_BODY_OFF = (NUMMONS + GLYPH_DETECT_FEM_OFF),
      GLYPH_RIDDEN_OFF = (NUMMONS + GLYPH_BODY_OFF),
      GLYPH_RIDDEN_MALE_OFF = (GLYPH_RIDDEN_OFF),
      GLYPH_RIDDEN_FEM_OFF = (NUMMONS + GLYPH_RIDDEN_MALE_OFF),
      GLYPH_OBJ_OFF = (NUMMONS + GLYPH_RIDDEN_FEM_OFF),
      GLYPH_CMAP_OFF = (NUM_OBJECTS + GLYPH_OBJ_OFF),
      GLYPH_CMAP_STONE_OFF = (GLYPH_CMAP_OFF),
      GLYPH_CMAP_MAIN_OFF = (1 + GLYPH_CMAP_STONE_OFF),
      GLYPH_CMAP_MINES_OFF = (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_MAIN_OFF),
      GLYPH_CMAP_GEH_OFF   = (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_MINES_OFF),
      GLYPH_CMAP_KNOX_OFF  = (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_GEH_OFF),
      GLYPH_CMAP_SOKO_OFF  = (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_KNOX_OFF),
      GLYPH_CMAP_A_OFF     = (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_SOKO_OFF),
      GLYPH_ALTAR_OFF = (((S_brdnladder - S_ndoor) + 1) + GLYPH_CMAP_A_OFF),
      GLYPH_CMAP_B_OFF = (5 + GLYPH_ALTAR_OFF),
      GLYPH_ZAP_OFF = (((S_vibrating_square - S_grave) + 1) + GLYPH_CMAP_B_OFF),
      GLYPH_CMAP_C_OFF = ((NUM_ZAP << 2) + GLYPH_ZAP_OFF),
      GLYPH_SWALLOW_OFF = (((S_goodpos - S_digbeam) + 1) + GLYPH_CMAP_C_OFF),
      GLYPH_EXPLODE_OFF = ((NUMMONS << 3) + GLYPH_SWALLOW_OFF),
      GLYPH_EXPLODE_DARK_OFF = (GLYPH_EXPLODE_OFF),
      GLYPH_EXPLODE_NOXIOUS_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_DARK_OFF),
      GLYPH_EXPLODE_MUDDY_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_NOXIOUS_OFF),
      GLYPH_EXPLODE_WET_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_MUDDY_OFF),
      GLYPH_EXPLODE_MAGICAL_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_WET_OFF),
      GLYPH_EXPLODE_FIERY_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_MAGICAL_OFF),
      GLYPH_EXPLODE_FROSTY_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_FIERY_OFF),
      GLYPH_WARNING_OFF = (MAXEXPCHARS + GLYPH_EXPLODE_FROSTY_OFF),
      GLYPH_STATUE_OFF = (WARNCOUNT + GLYPH_WARNING_OFF),
      GLYPH_STATUE_MALE_OFF = (GLYPH_STATUE_OFF),
      GLYPH_STATUE_FEM_OFF = (NUMMONS + GLYPH_STATUE_MALE_OFF),
      GLYPH_PILETOP_OFF = (NUMMONS + GLYPH_STATUE_FEM_OFF),
      GLYPH_OBJ_PILETOP_OFF = (GLYPH_PILETOP_OFF),
      GLYPH_BODY_PILETOP_OFF = (NUM_OBJECTS + GLYPH_OBJ_PILETOP_OFF),
      GLYPH_STATUE_MALE_PILETOP_OFF = (NUMMONS + GLYPH_BODY_PILETOP_OFF),
      GLYPH_STATUE_FEM_PILETOP_OFF = (NUMMONS + GLYPH_STATUE_MALE_PILETOP_OFF),
      GLYPH_UNEXPLORED_OFF = (NUMMONS + GLYPH_STATUE_FEM_PILETOP_OFF),
      GLYPH_NOTHING_OFF = (GLYPH_UNEXPLORED_OFF + 1),
      MAX_GLYPH
  };
  
  #define NO_GLYPH          MAX_GLYPH
  #define GLYPH_INVISIBLE   GLYPH_INVIS_OFF
  #define GLYPH_UNEXPLORED  GLYPH_UNEXPLORED_OFF
  #define GLYPH_NOTHING     GLYPH_NOTHING_OFF
  
  #define warning_to_glyph(mwarnlev) ((mwarnlev) + GLYPH_WARNING_OFF)
  #define mon_to_glyph(mon, rng) \
      ((int) what_mon(monsndx((mon)->data), rng) + \
              (((mon)->female == 0) ?  GLYPH_MON_MALE_OFF : GLYPH_MON_FEM_OFF))
  #define detected_mon_to_glyph(mon, rng) \
      ((int) what_mon(monsndx((mon)->data), rng) + \
              (((mon)->female == 0) ?  GLYPH_DETECT_MALE_OFF : GLYPH_DETECT_FEM_OFF))
  #define ridden_mon_to_glyph(mon, rng) \
      ((int) what_mon(monsndx((mon)->data), rng) + \
              (((mon)->female == 0) ?  GLYPH_RIDDEN_MALE_OFF : GLYPH_RIDDEN_FEM_OFF))
  #define pet_to_glyph(mon, rng) \
      ((int) what_mon(monsndx((mon)->data), rng) + \
              (((mon)->female == 0) ? GLYPH_PET_MALE_OFF : GLYPH_PET_FEM_OFF))
  
  #define altar_to_glyph(amsk) \
      (((amsk & (AM_MASK | AM_SHRINE)) == AM_NONE)               \
         ? (GLYPH_ALTAR_OFF + altar_unaligned)                   \
         : (((amsk & AM_SHRINE) == AM_SHRINE)                    \
            && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))      \
            ? (GLYPH_ALTAR_OFF + altar_other)                    \
            : ((amsk & AM_MASK) == AM_CHAOTIC)                   \
              ? (GLYPH_ALTAR_OFF + altar_chaotic)                \
              : ((amsk & AM_MASK) == AM_NEUTRAL)                 \
                ? (GLYPH_ALTAR_OFF + altar_neutral)              \
                : ((amsk & AM_MASK) == AM_LAWFUL)                \
                  ? (GLYPH_ALTAR_OFF + altar_lawful)             \
                  : (GLYPH_ALTAR_OFF + altar_neutral))
  
  /* not used, nor is it correct
  #define zap_to_glyph(zaptype, cmap_idx) \
      ((((cmap_idx) - S_vbeam) + 1) + GLYPH_ZAP_OFF)
  */
  
  #define explosion_to_glyph(expltyp, idx) \
      ((expltyp == EXPL_FROSTY) ?                                 \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_FROSTY_OFF)   \
       : (expltyp == EXPL_FIERY) ?                                \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_FIERY_OFF)    \
       : (expltyp == EXPL_MAGICAL) ?                              \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_MAGICAL_OFF)  \
       : (expltyp == EXPL_WET) ?                                  \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_WET_OFF)      \
       : (expltyp == EXPL_MUDDY) ?                                \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_MUDDY_OFF)    \
       : (expltyp == EXPL_NOXIOUS) ?                              \
              (((idx) - S_expl_tl) + GLYPH_EXPLODE_NOXIOUS_OFF)  \
       :       (((idx) - S_expl_tl) + GLYPH_EXPLODE_FIERY_OFF))
  
  #define cmap_walls_to_glyph(cmap_idx) \
       ( In_mines(&u.uz) ? (((cmap_idx) - S_vwall)  + GLYPH_CMAP_MINES_OFF)       \
       : In_hell(&u.uz) ? (((cmap_idx) - S_vwall) + GLYPH_CMAP_GEH_OFF)       \
       : Is_knox(&u.uz) ? (((cmap_idx) - S_vwall) + GLYPH_CMAP_KNOX_OFF)      \
       : In_sokoban(&u.uz) || In_sudoku(&u.uz) ? (((cmap_idx) - S_vwall) + GLYPH_CMAP_SOKO_OFF)  \
       : (((cmap_idx) - S_vwall) + GLYPH_CMAP_MAIN_OFF))
  
  #define cmap_a_to_glyph(cmap_idx) \
      (((cmap_idx) - S_ndoor) + GLYPH_CMAP_A_OFF)
  
  #define cmap_b_to_glyph(cmap_idx) \
      (((cmap_idx) - S_grave) + GLYPH_CMAP_B_OFF)
  
  #define cmap_c_to_glyph(cmap_idx) \
      (((cmap_idx) - S_digbeam) + GLYPH_CMAP_C_OFF)
  
  #define cmap_to_glyph(cmap_idx) \
          ( ((cmap_idx) == S_stone) ? GLYPH_CMAP_STONE_OFF                   \
          : ((cmap_idx) <= S_trwall) ? cmap_walls_to_glyph(cmap_idx)         \
          : ((cmap_idx) <  S_altar) ? cmap_a_to_glyph(cmap_idx)              \
          : ((cmap_idx) == S_altar) ? altar_to_glyph(AM_NEUTRAL)             \
          : ((cmap_idx) <= S_vibrating_square) ? cmap_b_to_glyph(cmap_idx)   \
          : ((cmap_idx) <= S_goodpos) ? cmap_c_to_glyph(cmap_idx)            \
          : NO_GLYPH)
  
  #define trap_to_glyph(trap)                                \
      cmap_to_glyph(trap_to_defsym(((int) (trap)->ttyp)))
  
  /* Not affected by hallucination.  Gives a generic body for CORPSE */
  /* MRKR: ...and the generic statue */
  #define objnum_to_glyph(onum) ((int) (onum) + GLYPH_OBJ_OFF)
  #define monnum_to_glyph(mnum,gnd) ((int) (mnum) + \
                          ((gnd == MALE) ? GLYPH_MON_MALE_OFF : GLYPH_MON_FEM_OFF))
  #define detected_monnum_to_glyph(mnum,gnd) ((int) (mnum) + \
                          ((gnd == MALE) ? GLYPH_DETECT_MALE_OFF : GLYPH_DETECT_FEM_OFF))
  #define ridden_monnum_to_glyph(mnum,gnd) ((int) (mnum) + \
                          ((gnd == MALE) ? GLYPH_RIDDEN_MALE_OFF : GLYPH_RIDDEN_FEM_OFF))
  #define petnum_to_glyph(mnum,gnd) ((int) (mnum) + \
                          ((gnd == MALE) ? GLYPH_PET_MALE_OFF : GLYPH_PET_FEM_OFF))
  
  /* The hero's glyph when seen as a monster.
   */
  #define hero_glyph                                                      \
      monnum_to_glyph((Upolyd || !flags.showrace)                         \
                          ? u.umonnum                                     \
                          : (flags.female && g.urace.femalenum != NON_PM) \
                                ? g.urace.femalenum                       \
                                : g.urace.malenum, (Ugender))
  
  /*
   * Change the given glyph into it's given type.  Note:
   *      1) Pets, detected, and ridden monsters are animals and are converted
   *         to the proper monster number.
   *      2) Bodies are all mapped into the generic CORPSE object
   *      3) If handed a glyph out of range for the type, these functions
   *         will return NO_GLYPH (see exception below)
   *      4) glyph_to_swallow() does not return a showsyms[] index, but an
   *         offset from the first swallow symbol.  If handed something
   *         out of range, it will return zero (for lack of anything better
   *         to return).
   */
  
  #define glyph_to_trap(glyph)                                                \
      (glyph_is_trap(glyph) \
          ? ((int) defsym_to_trap(((glyph) - GLYPH_TRAP_OFF) + S_arrow_trap)) \
          : NO_GLYPH)
  
  #define glyph_is_cmap_main(glyph) \
      ((glyph) >= GLYPH_CMAP_MAIN_OFF && \
          (glyph) < (((S_trwall - S_vwall) +1) + GLYPH_CMAP_MAIN_OFF))
  #define glyph_is_cmap_mines(glyph) \
      ((glyph) >= GLYPH_CMAP_MINES_OFF && \
          (glyph) < (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_MINES_OFF))
  #define glyph_is_cmap_gehennom(glyph) \
      ((glyph) >= GLYPH_CMAP_GEH_OFF && \
          (glyph) < (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_GEH_OFF))
  #define glyph_is_cmap_knox(glyph) \
      ((glyph) >= GLYPH_CMAP_KNOX_OFF && \
          (glyph) < (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_KNOX_OFF))
  #define glyph_is_cmap_sokoban(glyph) \
      ((glyph) >= GLYPH_CMAP_SOKO_OFF && \
          (glyph) < (((S_trwall - S_vwall) + 1) + GLYPH_CMAP_SOKO_OFF))
  #define glyph_is_cmap_a(glyph) \
      ((glyph) >= GLYPH_CMAP_A_OFF && \
          (glyph) < (((S_brdnladder - S_ndoor) + 1) + GLYPH_CMAP_A_OFF))
  #define glyph_is_cmap_altar(glyph) \
      ((glyph) >= GLYPH_ALTAR_OFF && \
          (glyph) < (5 + GLYPH_ALTAR_OFF))
  #define glyph_is_cmap_b(glyph) \
      ((glyph) >= GLYPH_CMAP_B_OFF && \
          ((glyph) < (((S_vibrating_square - S_grave) + 1) + GLYPH_CMAP_B_OFF)))
  #define glyph_is_cmap_zap(glyph) \
      ((glyph) >= GLYPH_ZAP_OFF && (glyph) < ((NUM_ZAP << 2) + GLYPH_ZAP_OFF))
  #define glyph_is_cmap_c(glyph) \
      ((glyph) >= GLYPH_CMAP_C_OFF && \
          (glyph) < (((S_goodpos - S_digbeam) + 1) + GLYPH_CMAP_C_OFF))
  #define glyph_is_swallow(glyph) \
      ((glyph) >= GLYPH_SWALLOW_OFF && (glyph) < (((NUMMONS << 3) + GLYPH_SWALLOW_OFF)))
  #define glyph_is_explosion(glyph) \
      ((glyph) >= GLYPH_EXPLODE_OFF && \
          (glyph) < (MAXEXPCHARS + GLYPH_EXPLODE_FROSTY_OFF))
  #define glyph_is_cmap(glyph) \
      (((glyph) == GLYPH_CMAP_STONE_OFF) \
       || glyph_is_cmap_main(glyph)      \
       || glyph_is_cmap_mines(glyph)     \
       || glyph_is_cmap_gehennom(glyph)  \
       || glyph_is_cmap_knox(glyph)      \
       || glyph_is_cmap_sokoban(glyph)   \
       || glyph_is_cmap_a(glyph)         \
       || glyph_is_cmap_altar(glyph)     \
       || glyph_is_cmap_b(glyph)         \
       || glyph_is_cmap_c(glyph))
  
  #define glyph_to_cmap(glyph) \
      (((glyph) == GLYPH_CMAP_STONE_OFF)                                 \
        ? S_stone                                                        \
        : glyph_is_cmap_main(glyph)                                      \
          ? (((glyph) - GLYPH_CMAP_MAIN_OFF) + S_vwall)                  \
          : glyph_is_cmap_mines(glyph)                                   \
            ? (((glyph) - GLYPH_CMAP_MINES_OFF) + S_vwall)               \
            : glyph_is_cmap_gehennom(glyph)                              \
              ? (((glyph) - GLYPH_CMAP_GEH_OFF) + S_vwall)               \
              : glyph_is_cmap_knox(glyph)                                \
                ? (((glyph) - GLYPH_CMAP_KNOX_OFF) + S_vwall)            \
                : glyph_is_cmap_sokoban(glyph)                           \
                  ? (((glyph) - GLYPH_CMAP_SOKO_OFF) + S_vwall)          \
                  : glyph_is_cmap_a(glyph)                               \
                    ? (((glyph) - GLYPH_CMAP_A_OFF) + S_ndoor)           \
                    : glyph_is_cmap_altar(glyph)                         \
                      ? (S_altar)                                        \
                      : glyph_is_cmap_b(glyph)                           \
                        ? (((glyph) - GLYPH_CMAP_B_OFF) + S_grave)       \
                        : glyph_is_cmap_c(glyph)                         \
                          ? (((glyph) - GLYPH_CMAP_C_OFF) + S_digbeam)   \
                          : NO_GLYPH)
  
  #define glyph_to_swallow(glyph) \
      (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : 0)
  #define glyph_to_warning(glyph) \
      (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : NO_GLYPH)
  
  /*
   * Return true if the given glyph is what we want.  Note that bodies are
   * considered objects.
   */
  #define glyph_is_normal_male_monster(glyph) \
      ((glyph) >= GLYPH_MON_MALE_OFF && (glyph) < (GLYPH_MON_MALE_OFF + NUMMONS))
  #define glyph_is_normal_female_monster(glyph) \
      ((glyph) >= GLYPH_MON_FEM_OFF && (glyph) < (GLYPH_MON_FEM_OFF + NUMMONS))
  #define glyph_is_normal_monster(glyph) \
      (glyph_is_normal_male_monster(glyph) || glyph_is_normal_female_monster(glyph))
  #define glyph_is_female_pet(glyph) \
      ((glyph) >= GLYPH_PET_FEM_OFF && (glyph) < (GLYPH_PET_FEM_OFF + NUMMONS))
  #define glyph_is_male_pet(glyph) \
      ((glyph) >= GLYPH_PET_MALE_OFF && (glyph) < (GLYPH_PET_MALE_OFF + NUMMONS))
  #define glyph_is_pet(glyph) \
      (glyph_is_male_pet(glyph) || glyph_is_female_pet(glyph))
  #define glyph_is_ridden_female_monster(glyph) \
      ((glyph) >= GLYPH_RIDDEN_FEM_OFF && (glyph) < \
          (GLYPH_RIDDEN_FEM_OFF + NUMMONS))
  #define glyph_is_ridden_male_monster(glyph) \
      ((glyph) >= GLYPH_RIDDEN_MALE_OFF && (glyph) < \
          (GLYPH_RIDDEN_MALE_OFF + NUMMONS))
  #define glyph_is_ridden_monster(glyph) \
      (glyph_is_ridden_male_monster(glyph) \
          || glyph_is_ridden_female_monster(glyph))
  #define glyph_is_detected_female_monster(glyph) \
      ((glyph) >= GLYPH_DETECT_FEM_OFF && (glyph) < \
          (GLYPH_DETECT_FEM_OFF + NUMMONS))
  #define glyph_is_detected_male_monster(glyph) \
      ((glyph) >= GLYPH_DETECT_MALE_OFF && (glyph) < \
          (GLYPH_DETECT_MALE_OFF + NUMMONS))
  #define glyph_is_detected_monster(glyph) \
      (glyph_is_detected_male_monster(glyph) \
          || glyph_is_detected_female_monster(glyph))
  #define glyph_is_monster(glyph)                            \
      (glyph_is_normal_monster(glyph) || glyph_is_pet(glyph) \
       || glyph_is_ridden_monster(glyph) || glyph_is_detected_monster(glyph))
  #define glyph_is_invisible(glyph) ((glyph) == GLYPH_INVISIBLE)
  
  #define glyph_to_mon(glyph) \
         (glyph_is_normal_female_monster(glyph)                  \
           ? ((glyph) - GLYPH_MON_FEM_OFF)                       \
           : glyph_is_normal_male_monster(glyph)                 \
             ? ((glyph) - GLYPH_MON_MALE_OFF)                    \
             : glyph_is_female_pet(glyph)                        \
               ? ((glyph) - GLYPH_PET_FEM_OFF)                   \
               : glyph_is_male_pet(glyph)                        \
                 ? ((glyph) - GLYPH_PET_MALE_OFF)                \
                 : glyph_is_detected_female_monster(glyph)       \
                   ? ((glyph) - GLYPH_DETECT_FEM_OFF)            \
                   : glyph_is_detected_male_monster(glyph)       \
                     ? ((glyph) - GLYPH_DETECT_MALE_OFF)         \
                     : glyph_is_ridden_female_monster(glyph)     \
                       ? ((glyph) - GLYPH_RIDDEN_FEM_OFF)        \
                       : glyph_is_ridden_male_monster(glyph)     \
                         ? ((glyph) - GLYPH_RIDDEN_MALE_OFF)     \
                         : NO_GLYPH)
  
  #define obj_is_piletop(obj) \
      ((obj)->where == OBJ_FLOOR                                   \
          && g.level.objects[(obj)->ox][(obj)->oy]                  \
              && g.level.objects[(obj)->ox][(obj)->oy]->nexthere)
  
  #define glyph_is_body_piletop(glyph) \
      (((glyph) >= GLYPH_BODY_PILETOP_OFF) \
                   && ((glyph) < (GLYPH_BODY_PILETOP_OFF + NUMMONS)))
  #define glyph_is_body(glyph) \
      ((((glyph) >= GLYPH_BODY_OFF) && ((glyph) < (GLYPH_BODY_OFF + NUMMONS))) \
      || glyph_is_body_piletop(glyph))
  
  #define glyph_is_fem_statue_piletop(glyph) \
      (((glyph) >= GLYPH_STATUE_FEM_PILETOP_OFF) \
        && ((glyph) < (GLYPH_STATUE_FEM_PILETOP_OFF + NUMMONS)))
  #define glyph_is_male_statue_piletop(glyph) \
       (((glyph) >= GLYPH_STATUE_MALE_PILETOP_OFF) \
           && ((glyph) < (GLYPH_STATUE_MALE_PILETOP_OFF + NUMMONS)))
  #define glyph_is_fem_statue(glyph) \
      ((((glyph) >= GLYPH_STATUE_FEM_OFF) && \
          ((glyph) < (GLYPH_STATUE_FEM_OFF + NUMMONS))) \
       || glyph_is_fem_statue_piletop(glyph))
  #define glyph_is_male_statue(glyph) \
      ((((glyph) >= GLYPH_STATUE_MALE_OFF) &&            \
          ((glyph) < (GLYPH_STATUE_MALE_OFF + NUMMONS))) \
       || glyph_is_male_statue_piletop(glyph))
  #define glyph_is_statue(glyph) \
      (glyph_is_male_statue(glyph) || glyph_is_fem_statue(glyph))
  #define glyph_is_normal_piletop_obj(glyph) \
      (((glyph) >= GLYPH_OBJ_PILETOP_OFF) && \
          ((glyph) < (GLYPH_OBJ_PILETOP_OFF + NUM_OBJECTS)))
  #define glyph_is_normal_object(glyph) \
       ((((glyph) >= GLYPH_OBJ_OFF) && \
          ((glyph) < (GLYPH_OBJ_OFF + NUM_OBJECTS))) \
        || glyph_is_normal_piletop_obj(glyph))
  
  #if 0
  #define glyph_is_object(glyph) \
  ((((glyph) >= GLYPH_OBJ_OFF) && ((glyph) < (GLYPH_OBJ_OFF + NUM_OBJECTS))) \
   || (((glyph) >= GLYPH_OBJ_PILETOP_OFF) \
       && ((glyph) < (GLYPH_OBJ_PILETOP_OFF + NUM_OBJECTS))) \
   || (((glyph) >= GLYPH_STATUE_MALE_OFF) \
       && ((glyph) < (GLYPH_STATUE_MALE_OFF + NUMMONS))) \
   || (((glyph) >= GLYPH_STATUE_MALE_PILETOP_OFF) \
       && ((glyph) < (GLYPH_STATUE_MALE_PILETOP_OFF + NUMMONS))) \
   || (((glyph) >= GLYPH_STATUE_FEM_OFF) \
       && ((glyph) < (GLYPH_STATUE_FEM_OFF + NUMMONS))) \
   || (((glyph) >= GLYPH_STATUE_FEM_PILETOP_OFF) \
       && ((glyph) < (GLYPH_STATUE_FEM_PILETOP_OFF + NUMMONS))) \
   || (((glyph) >= GLYPH_BODY_OFF) && ((glyph) < (GLYPH_BODY_OFF + NUMMONS))) \
   || (((glyph) >= GLYPH_BODY_PILETOP_OFF) \
       && ((glyph) < (GLYPH_BODY_PILETOP_OFF + NUMMONS))))
  #endif
  #define glyph_is_object(glyph)                               \
      (glyph_is_normal_object(glyph) || glyph_is_statue(glyph) \
       || glyph_is_body(glyph))
  
  /* briefly used for Qt's "paper doll" inventory which shows map tiles for
     equipped objects; those vary like floor items during hallucination now
     so this isn't used anywhere */
  #define obj_to_true_glyph(obj)                                  \
      (((obj)->otyp == STATUE)                                    \
       ? ((int) (obj)->corpsenm +                                 \
          (((obj)->spe & CORPSTAT_GENDER) == CORPSTAT_FEMALE)     \
               ? (obj_is_piletop(obj)                             \
                  ? (GLYPH_STATUE_FEM_PILETOP_OFF)                \
                  : (GLYPH_STATUE_FEM_OFF))                       \
               : (obj_is_piletop(obj)                             \
                  ? (GLYPH_STATUE_MALE_PILETOP_OFF)               \
                  : (GLYPH_STATUE_MALE_OFF))                      \
       : (((obj)->otyp == CORPSE)                                 \
           ? ((int) (obj)->corpsenm +                             \
               (obj_is_piletop(obj)                               \
                  ? (GLYPH_BODY_PILETOP_OFF)                      \
                  ? (GLYPH_BODY_OFF)))                            \
           : ((int) (obj)->otyp + GLYPH_OBJ_OFF))))
  
  #define glyph_to_obj(glyph) \
      (glyph_is_body(glyph)                            \
         ? CORPSE                                      \
         : glyph_is_statue(glyph)                      \
           ? STATUE                                    \
           : glyph_is_normal_object(glyph)             \
             ? ((glyph) -                              \
                 (glyph_is_normal_piletop_obj(glyph)   \
                   ? GLYPH_OBJ_PILETOP_OFF             \
                   : GLYPH_OBJ_OFF))                   \
             : NO_GLYPH)
  
  #define glyph_to_body_corpsenm(glyph) \
              (glyph_is_body_piletop(glyph)               \
                  ? ((glyph) - GLYPH_BODY_PILETOP_OFF)    \
                  : ((glyph) - GLYPH_BODY_OFF))
  
  #define glyph_to_statue_corpsenm(glyph) \
      (glyph_is_fem_statue_piletop(glyph)                 \
         ? ((glyph) - GLYPH_STATUE_FEM_PILETOP_OFF)       \
         : glyph_is_male_statue_piletop(glyph)            \
             ? ((glyph) - GLYPH_STATUE_MALE_PILETOP_OFF)  \
             : glyph_is_fem_statue(glyph)                 \
                 ? ((glyph) - GLYPH_STATUE_FEM_OFF)       \
                 : glyph_is_male_statue(glyph)            \
                     ? ((glyph) - GLYPH_STATUE_MALE_OFF)  \
                     : NO_GLYPH)
  
  /* These have the unfortunate side effect of needing a global variable    */
  /* to store a result. 'otg_temp' is defined and declared in decl.{ch}.  */
  #define random_obj_to_glyph(rng) \
      ((g.otg_temp = random_object(rng)) == CORPSE                   \
           ? (random_monster(rng) + GLYPH_BODY_OFF)                  \
           : (g.otg_temp + GLYPH_OBJ_OFF))
  #define corpse_to_glyph(obj) \
      ((int) ((obj)->corpsenm + (obj_is_piletop(obj)        \
                                  ? GLYPH_BODY_PILETOP_OFF  \
                                  : GLYPH_BODY_OFF)))
  
  /* Paraphrased rationale from the original commit for the boulder
     exception: If a boulder is the topmost item on a pile, then it is
     not mapped to a piletop glyph; mainly because boulders are "solid";
     boulders dropped by monsters are nearly always over other objects;
     also done so that special levels such a Sokoban can "hide" items
     under the boulders. */
  #define normal_obj_to_glyph(obj) \
      ((int) ((obj)->otyp + \
              ((obj_is_piletop(obj) && ((obj)->otyp != BOULDER))      \
                                  ? GLYPH_OBJ_PILETOP_OFF             \
                                  : GLYPH_OBJ_OFF)))
  
  /* MRKR: Statues now have glyphs corresponding to the monster they    */
  /*       represent and look like monsters when you are hallucinating. */
  
  #define statue_to_glyph(obj, rng) \
      ((Hallucination)                                                \
       ? ((random_monster(rng)) +                                     \
            ((!(rng)(2)) ? GLYPH_MON_MALE_OFF : GLYPH_MON_FEM_OFF))   \
       : ((int) (obj)->corpsenm +                                     \
                 ((((obj)->spe & CORPSTAT_GENDER) == CORPSTAT_FEMALE) \
                      ? (obj_is_piletop(obj)                          \
                            ? GLYPH_STATUE_FEM_PILETOP_OFF            \
                            : GLYPH_STATUE_FEM_OFF)                   \
                      : (obj_is_piletop(obj)                          \
                            ? GLYPH_STATUE_MALE_PILETOP_OFF           \
                            : GLYPH_STATUE_MALE_OFF))))
  
  #define obj_to_glyph(obj, rng) \
             (((obj)->otyp == STATUE)                   \
                 ? statue_to_glyph(obj, rng)            \
                 : ((Hallucination)                     \
                      ? random_obj_to_glyph(rng)        \
                      : (((obj)->otyp == CORPSE)        \
                          ? corpse_to_glyph(obj)        \
                          : normal_obj_to_glyph(obj))))
  
  #define GLYPH_TRAP_OFF \
      (GLYPH_CMAP_B_OFF + (S_arrow_trap - S_grave))
  #define glyph_is_trap(glyph)      \
      ((glyph) >= (GLYPH_TRAP_OFF) && \
       (glyph) < ((GLYPH_TRAP_OFF) + (TRAPNUM - 1)))
  #define glyph_is_warning(glyph)   \
      ((glyph) >= GLYPH_WARNING_OFF \
       && (glyph) < (GLYPH_WARNING_OFF + WARNCOUNT))
  #define glyph_is_unexplored(glyph) ((glyph) == GLYPH_UNEXPLORED)
  #define glyph_is_nothing(glyph) ((glyph) == GLYPH_NOTHING)
  
  /*
  #define glyph_is_piletop(glyph) \
      (glyph_is_body_piletop(glyph) || glyph_is_statue_piletop(glyph) \
          || glyph_is_obj_piletop(glyph))
  */
  
  /* mgflags for altering map_glyphinfo() internal behaviour */
  #define MG_FLAG_NORMAL      0x00
  #define MG_FLAG_NOOVERRIDE 0x01 /* disregard accessibility override values */
  
  /* Special mapped glyphflags encoded by reset_glyphmap() and/or map_glyphinfo() */
  #define MG_HERO    0x00001  /* represents the hero */
  #define MG_CORPSE  0x00002  /* represents a body */
  #define MG_INVIS   0x00004  /* represents invisible monster */
  #define MG_DETECT  0x00008  /* represents a detected monster */
  #define MG_PET     0x00010  /* represents a pet */
  #define MG_RIDDEN  0x00020  /* represents a ridden monster */
  #define MG_STATUE  0x00040  /* represents a statue */
  #define MG_OBJPILE 0x00080  /* more than one stack of objects */
  #define MG_BW_LAVA 0x00100  /* 'black & white lava': highlight lava if it
                                 can't be distringuished from water by color */
  #define MG_BW_ICE  0x00200  /* similar for ice vs floor */
  #define MG_NOTHING 0x00400  /* char represents GLYPH_NOTHING */
  #define MG_UNEXPL  0x00800  /* char represents GLYPH_UNEXPLORED */
  #define MG_MALE    0x01000  /* represents a male mon variation or statue of one */
  #define MG_FEMALE  0x02000  /* represents a female mon variation or statue of one */
  #define MG_BADXY   0x04000  /* bad coordinates were passed */
  
  typedef struct {
      xchar gnew; /* perhaps move this bit into the rm structure. */
      glyph_info glyphinfo;
  } gbuf_entry;
  
  #ifdef TEXTCOLOR
  extern const int altarcolors[];
  extern const int zapcolors[];
  extern const int explodecolors[];
  extern int wallcolors[];
  #endif
  
  /* If USE_TILES is defined during build, this comes from the generated
   * tile.c, complete with appropriate tile references in the initialization.
   * Otherwise, it comes from display.c.
   */
  extern const glyph_info nul_glyphinfo;
  
  #endif /* DISPLAY_H */
  