display.h

Go to the documentation of this file.
00001 /*      SCCS Id: @(#)display.h  3.4     1999/11/30      */
00002 /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
00003 /* and Dave Cohrs, 1990.                                          */
00004 /* NetHack may be freely redistributed.  See license for details. */
00005 
00006 #ifndef DISPLAY_H
00007 #define DISPLAY_H
00008 
00009 #ifndef VISION_H
00010 #include "vision.h"
00011 #endif
00012 
00013 #ifndef MONDATA_H
00014 #include "mondata.h"    /* for mindless() */
00015 #endif
00016 
00017 #ifndef INVISIBLE_OBJECTS
00018 #define vobj_at(x,y) (level.objects[x][y])
00019 #endif
00020 
00021 /*
00022  * sensemon()
00023  *
00024  * Returns true if the hero can sense the given monster.  This includes
00025  * monsters that are hiding or mimicing other monsters.
00026  */
00027 #define tp_sensemon(mon) (      /* The hero can always sense a monster IF:  */\
00028     (!mindless(mon->data) &&    /* 1. the monster has a brain to sense AND  */\
00029      (!which_armor(mon, W_ARMH) || which_armor(mon, W_ARMH)->otyp != TINFOIL_HAT)) && \
00030       ((Blind && Blind_telepat) ||      /* 2a. hero is blind and telepathic OR      */\
00031                                 /* 2b. hero is using a telepathy inducing   */\
00032                                 /*       object and in range                */\
00033                                 /* FALSE if monster is wearing a tinfoil hat*/\
00034       (Unblind_telepat &&                                             \
00035         (distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM))))                  \
00036 )
00037 
00038 #define sensemon(mon) (tp_sensemon(mon) || Detect_monsters || MATCH_WARN_OF_MON(mon))
00039 
00040 /*
00041  * mon_warning() is used to warn of any dangerous monsters in your
00042  * vicinity, and a glyph representing the warning level is displayed.
00043  */
00044 
00045 #define mon_warning(mon) (Warning && !(mon)->mpeaceful &&                               \
00046                          (distu((mon)->mx, (mon)->my) < 100) &&                         \
00047                          (((int) ((mon)->m_lev / 4)) >= flags.warnlevel))
00048 
00049 /*
00050  * mon_visible()
00051  *
00052  * Returns true if the hero can see the monster.  It is assumed that the
00053  * hero can physically see the location of the monster.  The function
00054  * vobj_at() returns a pointer to an object that the hero can see there.
00055  * Infravision is not taken into account.
00056  */
00057 #define mon_visible(mon) (              /* The hero can see the monster     */\
00058                                         /* IF the monster                   */\
00059     (!mon->minvis || See_invisible) &&  /* 1. is not invisible AND          */\
00060     (!mon->mundetected) &&              /* 2. not an undetected hider       */\
00061     (!(mon->mburied || u.uburied))      /* 3. neither you or it is buried   */\
00062 )
00063 
00064 /*
00065  * see_with_infrared()
00066  *
00067  * This function is true if the player can see a monster using infravision.
00068  * The caller must check for invisibility (invisible monsters are also
00069  * invisible to infravision), because this is usually called from within
00070  * canseemon() or canspotmon() which already check that.
00071  */
00072 #define see_with_infrared(mon) (!Blind && Infravision && infravisible(mon->data) && couldsee(mon->mx, mon->my))
00073 
00074 
00075 /*
00076  * canseemon()
00077  *
00078  * This is the globally used canseemon().  It is not called within the display
00079  * routines.  Like mon_visible(), but it checks to see if the hero sees the
00080  * location instead of assuming it.  (And also considers worms.)
00081  */
00082 #define canseemon(mon) ((mon->wormno ? worm_known(mon) : \
00083             (cansee(mon->mx, mon->my) || see_with_infrared(mon))) \
00084         && mon_visible(mon))
00085 
00086 
00087 /*
00088  * canspotmon(mon)
00089  *
00090  * This function checks whether you can either see a monster or sense it by
00091  * telepathy, and is what you usually call for monsters about which nothing is
00092  * known.
00093  */
00094 #define canspotmon(mon) \
00095         (canseemon(mon) || sensemon(mon))
00096 
00097 /* knowninvisible(mon)
00098  * This one checks to see if you know a monster is both there and invisible.
00099  * 1) If you can see the monster and have see invisible, it is assumed the
00100  * monster is transparent, but visible in some manner.  (Earlier versions of
00101  * Nethack were really inconsistent on this.)
00102  * 2) If you can't see the monster, but can see its location and you have
00103  * telepathy that works when you can see, you can tell that there is a
00104  * creature in an apparently empty spot.
00105  * Infravision is not relevant; we assume that invisible monsters are also
00106  * invisible to infravision.
00107  */
00108 #define knowninvisible(mon) \
00109         (mtmp->minvis && \
00110             ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) || \
00111                 (!Blind && (HTelepat & ~INTRINSIC) && \
00112                     distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM) \
00113                 ) \
00114             ) \
00115         )
00116 
00117 /*
00118  * is_safepet(mon)
00119  *
00120  * A special case check used in attack() and domove().  Placing the
00121  * definition here is convenient.
00122  */
00123 #define is_safepet(mon) \
00124         (mon && mon->mtame && canspotmon(mon) && flags.safe_dog \
00125                 && !Confusion && !Hallucination && !Stunned)
00126 
00127 
00128 /*
00129  * canseeself()
00130  * senseself()
00131  *
00132  * This returns true if the hero can see her/himself.
00133  *
00134  * The u.uswallow check assumes that you can see yourself even if you are
00135  * invisible.  If not, then we don't need the check.
00136  */
00137 #define canseeself()    (Blind || u.uswallow || (!Invisible && !u.uundetected))
00138 #define senseself()     (canseeself() || Unblind_telepat || Detect_monsters)
00139 
00140 /*
00141  * random_monster()
00142  * random_object()
00143  * random_trap()
00144  *
00145  * Respectively return a random monster, object, or trap number.
00146  */
00147 #define random_monster() rn2(NUMMONS)
00148 #define random_object()  rn1(NUM_OBJECTS-1,1)
00149 #define random_trap()    rn1(TRAPNUM-1,1)
00150 
00151 /*
00152  * what_obj()
00153  * what_mon()
00154  * what_trap()
00155  *
00156  * If hallucinating, choose a random object/monster, otherwise, use the one
00157  * given.
00158  */
00159 #define what_obj(obj)   (Hallucination ? random_object()  : obj)
00160 #define what_mon(mon)   (Hallucination ? random_monster() : mon)
00161 #define what_trap(trp)  (Hallucination ? random_trap()    : trp)
00162 
00163 /*
00164  * covers_objects()
00165  * covers_traps()
00166  *
00167  * These routines are true if what is really at the given location will
00168  * "cover" any objects or traps that might be there.
00169  */
00170 #define covers_objects(xx,yy)                                                 \
00171     ((is_pool(xx,yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL))
00172 
00173 #define covers_traps(xx,yy)     covers_objects(xx,yy)
00174 
00175 
00176 /*
00177  * tmp_at() control calls.
00178  */
00179 #define DISP_BEAM    (-1)  /* Keep all glyphs showing & clean up at end. */
00180 #define DISP_FLASH   (-2)  /* Clean up each glyph before displaying new one. */
00181 #define DISP_ALWAYS  (-3)  /* Like flash, but still displayed if not visible. */
00182 #define DISP_CHANGE  (-4)  /* Change glyph. */
00183 #define DISP_END     (-5)  /* Clean up. */
00184 #define DISP_FREEMEM (-6)  /* Free all memory during exit only. */
00185 
00186 
00187 /* Total number of cmap indices in the sheild_static[] array. */
00188 #define SHIELD_COUNT 21
00189 
00190 
00191 /*
00192  * display_self()
00193  *
00194  * Display the hero.  It is assumed that all checks necessary to determine
00195  * _if_ the hero can be seen have already been done.
00196  */
00197 #ifdef STEED
00198 #define maybe_display_usteed    (u.usteed && mon_visible(u.usteed)) ? \
00199                                         ridden_mon_to_glyph(u.usteed) :
00200 #else
00201 #define maybe_display_usteed    /* empty */
00202 #endif
00203 
00204 #define display_self()                                                  \
00205     show_glyph(u.ux, u.uy,                                              \
00206         maybe_display_usteed                    /* else */              \
00207         youmonst.m_ap_type == M_AP_NOTHING ?                            \
00208                                 hero_glyph :                            \
00209         youmonst.m_ap_type == M_AP_FURNITURE ?                          \
00210                                 cmap_to_glyph(youmonst.mappearance) :   \
00211         youmonst.m_ap_type == M_AP_OBJECT ?                             \
00212                                 objnum_to_glyph(youmonst.mappearance) : \
00213         /* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance))
00214 
00215 /*
00216  * A glyph is an abstraction that represents a _unique_ monster, object,
00217  * dungeon part, or effect.  The uniqueness is important.  For example,
00218  * It is not enough to have four (one for each "direction") zap beam glyphs,
00219  * we need a set of four for each beam type.  Why go to so much trouble?
00220  * Because it is possible that any given window dependent display driver
00221  * [print_glyph()] can produce something different for each type of glyph.
00222  * That is, a beam of cold and a beam of fire would not only be different
00223  * colors, but would also be represented by different symbols.
00224  *
00225  * Glyphs are grouped for easy accessibility:
00226  *
00227  * monster      Represents all the wild (not tame) monsters.  Count: NUMMONS.
00228  *
00229  * pet          Represents all of the tame monsters.  Count: NUMMONS
00230  *
00231  * invisible    Invisible monster placeholder.  Count: 1
00232  *
00233  * detect       Represents all detected monsters.  Count: NUMMONS
00234  *
00235  * corpse       One for each monster.  Count: NUMMONS
00236  *
00237  * ridden       Represents all monsters being ridden.  Count: NUMMONS 
00238  *
00239  * object       One for each object.  Count: NUM_OBJECTS
00240  *
00241  * cmap         One for each entry in the character map.  The character map
00242  *              is the dungeon features and other miscellaneous things.
00243  *              Count: MAXPCHARS
00244  *
00245  * explosions   A set of nine for each of the following seven explosion types:
00246  *                   dark, noxious, muddy, wet, magical, fiery, frosty.
00247  *              The nine positions represent those surrounding the hero.
00248  *              Count: MAXEXPCHARS * EXPL_MAX (EXPL_MAX is defined in hack.h)
00249  *
00250  * zap beam     A set of four (there are four directions) for each beam type.
00251  *              The beam type is shifted over 2 positions and the direction
00252  *              is stored in the lower 2 bits.  Count: NUM_ZAP << 2
00253  *
00254  * swallow      A set of eight for each monster.  The eight positions rep-
00255  *              resent those surrounding the hero.  The monster number is
00256  *              shifted over 3 positions and the swallow position is stored
00257  *              in the lower three bits.  Count: NUMMONS << 3
00258  *
00259  * warning      A set of six representing the different warning levels.
00260  *
00261  * The following are offsets used to convert to and from a glyph.
00262  */
00263 #define NUM_ZAP 8       /* number of zap beam types */
00264 
00265 #define GLYPH_MON_OFF           0
00266 #define GLYPH_PET_OFF           (NUMMONS        + GLYPH_MON_OFF)
00267 #define GLYPH_INVIS_OFF         (NUMMONS        + GLYPH_PET_OFF)
00268 #define GLYPH_DETECT_OFF        (1              + GLYPH_INVIS_OFF)
00269 #define GLYPH_BODY_OFF          (NUMMONS        + GLYPH_DETECT_OFF)
00270 #define GLYPH_RIDDEN_OFF        (NUMMONS        + GLYPH_BODY_OFF)
00271 #define GLYPH_OBJ_OFF           (NUMMONS        + GLYPH_RIDDEN_OFF)
00272 #define GLYPH_CMAP_OFF          (NUM_OBJECTS    + GLYPH_OBJ_OFF)
00273 #define GLYPH_EXPLODE_OFF       ((MAXPCHARS - MAXEXPCHARS) + GLYPH_CMAP_OFF)
00274 #define GLYPH_ZAP_OFF           ((MAXEXPCHARS * EXPL_MAX) + GLYPH_EXPLODE_OFF)
00275 #define GLYPH_SWALLOW_OFF       ((NUM_ZAP << 2) + GLYPH_ZAP_OFF)
00276 #define GLYPH_WARNING_OFF       ((NUMMONS << 3) + GLYPH_SWALLOW_OFF)
00277 #define MAX_GLYPH               (WARNCOUNT      + GLYPH_WARNING_OFF)
00278 
00279 #define NO_GLYPH MAX_GLYPH
00280 
00281 #define GLYPH_INVISIBLE GLYPH_INVIS_OFF
00282 
00283 #define warning_to_glyph(mwarnlev) ((mwarnlev)+GLYPH_WARNING_OFF)
00284 #define mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_MON_OFF)
00285 #define detected_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_DETECT_OFF)
00286 #define ridden_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_RIDDEN_OFF)
00287 #define pet_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_PET_OFF)
00288 
00289 /* This has the unfortunate side effect of needing a global variable    */
00290 /* to store a result. 'otg_temp' is defined and declared in decl.{ch}.  */
00291 #define obj_to_glyph(obj)                                                     \
00292     (Hallucination ?                                                          \
00293         ((otg_temp = random_object()) == CORPSE ?                             \
00294             random_monster() + GLYPH_BODY_OFF :                               \
00295             otg_temp + GLYPH_OBJ_OFF)   :                                     \
00296         ((obj)->otyp == CORPSE ?                                              \
00297             (int) (obj)->corpsenm + GLYPH_BODY_OFF :                          \
00298             (int) (obj)->otyp + GLYPH_OBJ_OFF))
00299 
00300 #define cmap_to_glyph(cmap_idx) ((int) (cmap_idx)   + GLYPH_CMAP_OFF)
00301 #define explosion_to_glyph(expltype,idx)        \
00302                 ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF)
00303 
00304 #define trap_to_glyph(trap)     \
00305                         cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp)))
00306 
00307 /* Not affected by hallucination.  Gives a generic body for CORPSE */
00308 #define objnum_to_glyph(onum)   ((int) (onum) + GLYPH_OBJ_OFF)
00309 #define monnum_to_glyph(mnum)   ((int) (mnum) + GLYPH_MON_OFF)
00310 #define detected_monnum_to_glyph(mnum)  ((int) (mnum) + GLYPH_DETECT_OFF)
00311 #define ridden_monnum_to_glyph(mnum)    ((int) (mnum) + GLYPH_RIDDEN_OFF)
00312 #define petnum_to_glyph(mnum)   ((int) (mnum) + GLYPH_PET_OFF)
00313 
00314 /* The hero's glyph when seen as a monster.
00315  */
00316 #define hero_glyph \
00317         monnum_to_glyph((Upolyd || !iflags.showrace) ? u.umonnum : \
00318                         (flags.female && urace.femalenum != NON_PM) ? urace.femalenum : \
00319                         urace.malenum)
00320 
00321 
00322 /*
00323  * Change the given glyph into it's given type.  Note:
00324  *      1) Pets, detected, and ridden monsters are animals and are converted
00325  *         to the proper monster number.
00326  *      2) Bodies are all mapped into the generic CORPSE object
00327  *      3) If handed a glyph out of range for the type, these functions
00328  *         will return NO_GLYPH (see exception below)
00329  *      4) glyph_to_swallow() does not return a showsyms[] index, but an
00330  *         offset from the first swallow symbol.  If handed something
00331  *         out of range, it will return zero (for lack of anything better
00332  *         to return).
00333  */
00334 #define glyph_to_mon(glyph)                                             \
00335         (glyph_is_normal_monster(glyph) ? ((glyph)-GLYPH_MON_OFF) :     \
00336         glyph_is_pet(glyph) ? ((glyph)-GLYPH_PET_OFF) :                 \
00337         glyph_is_detected_monster(glyph) ? ((glyph)-GLYPH_DETECT_OFF) : \
00338         glyph_is_ridden_monster(glyph) ? ((glyph)-GLYPH_RIDDEN_OFF) :   \
00339         NO_GLYPH)
00340 #define glyph_to_obj(glyph)                                             \
00341         (glyph_is_body(glyph) ? CORPSE :                                \
00342         glyph_is_normal_object(glyph) ? ((glyph)-GLYPH_OBJ_OFF) :       \
00343         NO_GLYPH)
00344 #define glyph_to_trap(glyph)                                            \
00345         (glyph_is_trap(glyph) ?                                         \
00346                 ((int) defsym_to_trap((glyph) - GLYPH_CMAP_OFF)) :      \
00347         NO_GLYPH)
00348 #define glyph_to_cmap(glyph)                                            \
00349         (glyph_is_cmap(glyph) ? ((glyph) - GLYPH_CMAP_OFF) :            \
00350         NO_GLYPH)
00351 #define glyph_to_swallow(glyph)                                         \
00352         (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : \
00353         0)
00354 #define glyph_to_warning(glyph)                                         \
00355         (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) :      \
00356         NO_GLYPH);
00357 
00358 /*
00359  * Return true if the given glyph is what we want.  Note that bodies are
00360  * considered objects.
00361  */
00362 #define glyph_is_monster(glyph)                                         \
00363                 (glyph_is_normal_monster(glyph)                         \
00364                 || glyph_is_pet(glyph)                                  \
00365                 || glyph_is_ridden_monster(glyph)                       \
00366                 || glyph_is_detected_monster(glyph))
00367 #define glyph_is_normal_monster(glyph)                                  \
00368     ((glyph) >= GLYPH_MON_OFF && (glyph) < (GLYPH_MON_OFF+NUMMONS))
00369 #define glyph_is_pet(glyph)                                             \
00370     ((glyph) >= GLYPH_PET_OFF && (glyph) < (GLYPH_PET_OFF+NUMMONS))
00371 #define glyph_is_body(glyph)                                            \
00372     ((glyph) >= GLYPH_BODY_OFF && (glyph) < (GLYPH_BODY_OFF+NUMMONS))
00373 #define glyph_is_ridden_monster(glyph)                                  \
00374     ((glyph) >= GLYPH_RIDDEN_OFF && (glyph) < (GLYPH_RIDDEN_OFF+NUMMONS))
00375 #define glyph_is_detected_monster(glyph)                                \
00376     ((glyph) >= GLYPH_DETECT_OFF && (glyph) < (GLYPH_DETECT_OFF+NUMMONS))
00377 #define glyph_is_invisible(glyph) ((glyph) == GLYPH_INVISIBLE)
00378 #define glyph_is_normal_object(glyph)                                   \
00379     ((glyph) >= GLYPH_OBJ_OFF && (glyph) < (GLYPH_OBJ_OFF+NUM_OBJECTS))
00380 #define glyph_is_object(glyph)                                          \
00381                 (glyph_is_normal_object(glyph)                          \
00382                 || glyph_is_body(glyph))
00383 #define glyph_is_trap(glyph)                                            \
00384     ((glyph) >= (GLYPH_CMAP_OFF+trap_to_defsym(1)) &&                   \
00385      (glyph) <  (GLYPH_CMAP_OFF+trap_to_defsym(1)+TRAPNUM))
00386 #define glyph_is_cmap(glyph)                                            \
00387     ((glyph) >= GLYPH_CMAP_OFF && (glyph) < (GLYPH_CMAP_OFF+MAXPCHARS))
00388 #define glyph_is_swallow(glyph) \
00389     ((glyph) >= GLYPH_SWALLOW_OFF && (glyph) < (GLYPH_SWALLOW_OFF+(NUMMONS << 3)))
00390 #define glyph_is_warning(glyph) \
00391     ((glyph) >= GLYPH_WARNING_OFF && (glyph) < (GLYPH_WARNING_OFF + WARNCOUNT))
00392 #endif /* DISPLAY_H */