1/* SCCS Id: @(#)display.h 3.4 1999/11/30 */ 2/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ 3/* and Dave Cohrs, 1990. */ 4/* NetHack may be freely redistributed. See license for details. */ 5 6#ifndef DISPLAY_H 7#define DISPLAY_H 8 9#ifndef VISION_H 10#include "vision.h" 11#endif 12 13#ifndef MONDATA_H 14#include "mondata.h" /* for mindless() */ 15#endif 16 17#ifndef INVISIBLE_OBJECTS 18#define vobj_at(x,y) (level.objects[x][y]) 19#endif 20 21/* 22 * sensemon() 23 * 24 * Returns true if the hero can sense the given monster. This includes 25 * monsters that are hiding or mimicing other monsters. 26 */ 27#define tp_sensemon(mon) ( /* The hero can always sense a monster IF: */\ 28 (!mindless(mon->data)) && /* 1. the monster has a brain to sense AND */\ 29 ((Blind && Blind_telepat) || /* 2a. hero is blind and telepathic OR */\ 30 /* 2b. hero is using a telepathy inducing */\ 31 /* object and in range */\ 32 (Unblind_telepat && \ 33 (distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM)))) \ 34) 35 36#define sensemon(mon) (tp_sensemon(mon) || Detect_monsters || MATCH_WARN_OF_MON(mon)) 37 38/* 39 * mon_warning() is used to warn of any dangerous monsters in your 40 * vicinity, and a glyph representing the warning level is displayed. 41 */ 42 43#define mon_warning(mon) (Warning && !(mon)->mpeaceful && \ 44 (distu((mon)->mx, (mon)->my) < 100) && \ 45 (((int) ((mon)->m_lev / 4)) >= flags.warnlevel)) 46 47/* 48 * mon_visible() 49 * 50 * Returns true if the hero can see the monster. It is assumed that the 51 * hero can physically see the location of the monster. The function 52 * vobj_at() returns a pointer to an object that the hero can see there. 53 * Infravision is not taken into account. 54 */ 55#define mon_visible(mon) ( /* The hero can see the monster */\ 56 /* IF the monster */\ 57 (!mon->minvis || See_invisible) && /* 1. is not invisible AND */\ 58 (!mon->mundetected) && /* 2. not an undetected hider */\ 59 (!(mon->mburied || u.uburied)) /* 3. neither you or it is buried */\ 60) 61 62/* 63 * see_with_infrared() 64 * 65 * This function is true if the player can see a monster using infravision. 66 * The caller must check for invisibility (invisible monsters are also 67 * invisible to infravision), because this is usually called from within 68 * canseemon() or canspotmon() which already check that. 69 */ 70#define see_with_infrared(mon) (!Blind && Infravision && infravisible(mon->data) && couldsee(mon->mx, mon->my)) 71 72 73/* 74 * canseemon() 75 * 76 * This is the globally used canseemon(). It is not called within the display 77 * routines. Like mon_visible(), but it checks to see if the hero sees the 78 * location instead of assuming it. (And also considers worms.) 79 */ 80#define canseemon(mon) ((mon->wormno ? worm_known(mon) : \ 81 (cansee(mon->mx, mon->my) || see_with_infrared(mon))) \ 82 && mon_visible(mon)) 83 84 85/* 86 * canspotmon(mon) 87 * 88 * This function checks whether you can either see a monster or sense it by 89 * telepathy, and is what you usually call for monsters about which nothing is 90 * known. 91 */ 92#define canspotmon(mon) \ 93 (canseemon(mon) || sensemon(mon)) 94 95/* knowninvisible(mon) 96 * This one checks to see if you know a monster is both there and invisible. 97 * 1) If you can see the monster and have see invisible, it is assumed the 98 * monster is transparent, but visible in some manner. (Earlier versions of 99 * Nethack were really inconsistent on this.) 100 * 2) If you can't see the monster, but can see its location and you have 101 * telepathy that works when you can see, you can tell that there is a 102 * creature in an apparently empty spot. 103 * Infravision is not relevant; we assume that invisible monsters are also 104 * invisible to infravision. 105 */ 106#define knowninvisible(mon) \ 107 (mtmp->minvis && \ 108 ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) || \ 109 (!Blind && (HTelepat & ~INTRINSIC) && \ 110 distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM) \ 111 ) \ 112 ) \ 113 ) 114 115/* 116 * is_safepet(mon) 117 * 118 * A special case check used in attack() and domove(). Placing the 119 * definition here is convenient. 120 */ 121#define is_safepet(mon) \ 122 (mon && mon->mtame && canspotmon(mon) && flags.safe_dog \ 123 && !Confusion && !Hallucination && !Stunned) 124 125 126/* 127 * canseeself() 128 * senseself() 129 * 130 * This returns true if the hero can see her/himself. 131 * 132 * The u.uswallow check assumes that you can see yourself even if you are 133 * invisible. If not, then we don't need the check. 134 */ 135#define canseeself() (Blind || u.uswallow || (!Invisible && !u.uundetected)) 136#define senseself() (canseeself() || Unblind_telepat || Detect_monsters) 137 138/* 139 * random_monster() 140 * random_object() 141 * random_trap() 142 * 143 * Respectively return a random monster, object, or trap number. 144 */ 145#define random_monster() rn2(NUMMONS) 146#define random_object() rn1(NUM_OBJECTS-1,1) 147#define random_trap() rn1(TRAPNUM-1,1) 148 149/* 150 * what_obj() 151 * what_mon() 152 * what_trap() 153 * 154 * If hallucinating, choose a random object/monster, otherwise, use the one 155 * given. 156 */ 157#define what_obj(obj) (Hallucination ? random_object() : obj) 158#define what_mon(mon) (Hallucination ? random_monster() : mon) 159#define what_trap(trp) (Hallucination ? random_trap() : trp) 160 161/* 162 * covers_objects() 163 * covers_traps() 164 * 165 * These routines are true if what is really at the given location will 166 * "cover" any objects or traps that might be there. 167 */ 168#define covers_objects(xx,yy) \ 169 ((is_pool(xx,yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL)) 170 171#define covers_traps(xx,yy) covers_objects(xx,yy) 172 173 174/* 175 * tmp_at() control calls. 176 */ 177#define DISP_BEAM (-1) /* Keep all glyphs showing & clean up at end. */ 178#define DISP_FLASH (-2) /* Clean up each glyph before displaying new one. */ 179#define DISP_ALWAYS (-3) /* Like flash, but still displayed if not visible. */ 180#define DISP_CHANGE (-4) /* Change glyph. */ 181#define DISP_END (-5) /* Clean up. */ 182#define DISP_FREEMEM (-6) /* Free all memory during exit only. */ 183 184 185/* Total number of cmap indices in the sheild_static[] array. */ 186#define SHIELD_COUNT 21 187 188 189/* 190 * display_self() 191 * 192 * Display the hero. It is assumed that all checks necessary to determine 193 * _if_ the hero can be seen have already been done. 194 */ 195#ifdef STEED 196#define maybe_display_usteed (u.usteed && mon_visible(u.usteed)) ? \ 197 ridden_mon_to_glyph(u.usteed) : 198#else 199#define maybe_display_usteed /* empty */ 200#endif 201 202#define display_self() \ 203 show_glyph(u.ux, u.uy, \ 204 maybe_display_usteed /* else */ \ 205 youmonst.m_ap_type == M_AP_NOTHING ? \ 206 hero_glyph : \ 207 youmonst.m_ap_type == M_AP_FURNITURE ? \ 208 cmap_to_glyph(youmonst.mappearance) : \ 209 youmonst.m_ap_type == M_AP_OBJECT ? \ 210 objnum_to_glyph(youmonst.mappearance) : \ 211 /* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance)) 212 213/* 214 * A glyph is an abstraction that represents a _unique_ monster, object, 215 * dungeon part, or effect. The uniqueness is important. For example, 216 * It is not enough to have four (one for each "direction") zap beam glyphs, 217 * we need a set of four for each beam type. Why go to so much trouble? 218 * Because it is possible that any given window dependent display driver 219 * [print_glyph()] can produce something different for each type of glyph. 220 * That is, a beam of cold and a beam of fire would not only be different 221 * colors, but would also be represented by different symbols. 222 * 223 * Glyphs are grouped for easy accessibility: 224 * 225 * monster Represents all the wild (not tame) monsters. Count: NUMMONS. 226 * 227 * pet Represents all of the tame monsters. Count: NUMMONS 228 * 229 * invisible Invisible monster placeholder. Count: 1 230 * 231 * detect Represents all detected monsters. Count: NUMMONS 232 * 233 * corpse One for each monster. Count: NUMMONS 234 * 235 * ridden Represents all monsters being ridden. Count: NUMMONS 236 * 237 * object One for each object. Count: NUM_OBJECTS 238 * 239 * cmap One for each entry in the character map. The character map 240 * is the dungeon features and other miscellaneous things. 241 * Count: MAXPCHARS 242 * 243 * explosions A set of nine for each of the following seven explosion types: 244 * dark, noxious, muddy, wet, magical, fiery, frosty. 245 * The nine positions represent those surrounding the hero. 246 * Count: MAXEXPCHARS * EXPL_MAX (EXPL_MAX is defined in hack.h) 247 * 248 * zap beam A set of four (there are four directions) for each beam type. 249 * The beam type is shifted over 2 positions and the direction 250 * is stored in the lower 2 bits. Count: NUM_ZAP << 2 251 * 252 * swallow A set of eight for each monster. The eight positions rep- 253 * resent those surrounding the hero. The monster number is 254 * shifted over 3 positions and the swallow position is stored 255 * in the lower three bits. Count: NUMMONS << 3 256 * 257 * warning A set of six representing the different warning levels. 258 * 259 * The following are offsets used to convert to and from a glyph. 260 */ 261#define NUM_ZAP 8 /* number of zap beam types */ 262 263#define GLYPH_MON_OFF 0 264#define GLYPH_PET_OFF (NUMMONS + GLYPH_MON_OFF) 265#define GLYPH_INVIS_OFF (NUMMONS + GLYPH_PET_OFF) 266#define GLYPH_DETECT_OFF (1 + GLYPH_INVIS_OFF) 267#define GLYPH_BODY_OFF (NUMMONS + GLYPH_DETECT_OFF) 268#define GLYPH_RIDDEN_OFF (NUMMONS + GLYPH_BODY_OFF) 269#define GLYPH_OBJ_OFF (NUMMONS + GLYPH_RIDDEN_OFF) 270#define GLYPH_CMAP_OFF (NUM_OBJECTS + GLYPH_OBJ_OFF) 271#define GLYPH_EXPLODE_OFF ((MAXPCHARS - MAXEXPCHARS) + GLYPH_CMAP_OFF) 272#define GLYPH_ZAP_OFF ((MAXEXPCHARS * EXPL_MAX) + GLYPH_EXPLODE_OFF) 273#define GLYPH_SWALLOW_OFF ((NUM_ZAP << 2) + GLYPH_ZAP_OFF) 274#define GLYPH_WARNING_OFF ((NUMMONS << 3) + GLYPH_SWALLOW_OFF) 275#define MAX_GLYPH (WARNCOUNT + GLYPH_WARNING_OFF) 276 277#define NO_GLYPH MAX_GLYPH 278 279#define GLYPH_INVISIBLE GLYPH_INVIS_OFF 280 281#define warning_to_glyph(mwarnlev) ((mwarnlev)+GLYPH_WARNING_OFF) 282#define mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_MON_OFF) 283#define detected_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_DETECT_OFF) 284#define ridden_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_RIDDEN_OFF) 285#define pet_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_PET_OFF) 286 287/* This has the unfortunate side effect of needing a global variable */ 288/* to store a result. 'otg_temp' is defined and declared in decl.{ch}. */ 289#define obj_to_glyph(obj) \ 290 (Hallucination ? \ 291 ((otg_temp = random_object()) == CORPSE ? \ 292 random_monster() + GLYPH_BODY_OFF : \ 293 otg_temp + GLYPH_OBJ_OFF) : \ 294 ((obj)->otyp == CORPSE ? \ 295 (int) (obj)->corpsenm + GLYPH_BODY_OFF : \ 296 (int) (obj)->otyp + GLYPH_OBJ_OFF)) 297 298#define cmap_to_glyph(cmap_idx) ((int) (cmap_idx) + GLYPH_CMAP_OFF) 299#define explosion_to_glyph(expltype,idx) \ 300 ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF) 301 302#define trap_to_glyph(trap) \ 303 cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp))) 304 305/* Not affected by hallucination. Gives a generic body for CORPSE */ 306#define objnum_to_glyph(onum) ((int) (onum) + GLYPH_OBJ_OFF) 307#define monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_MON_OFF) 308#define detected_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_DETECT_OFF) 309#define ridden_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_RIDDEN_OFF) 310#define petnum_to_glyph(mnum) ((int) (mnum) + GLYPH_PET_OFF) 311 312/* The hero's glyph when seen as a monster. 313 */ 314#define hero_glyph \ 315 monnum_to_glyph((Upolyd || !iflags.showrace) ? u.umonnum : \ 316 (flags.female && urace.femalenum != NON_PM) ? urace.femalenum : \ 317 urace.malenum) 318 319 320/* 321 * Change the given glyph into it's given type. Note: 322 * 1) Pets, detected, and ridden monsters are animals and are converted 323 * to the proper monster number. 324 * 2) Bodies are all mapped into the generic CORPSE object 325 * 3) If handed a glyph out of range for the type, these functions 326 * will return NO_GLYPH (see exception below) 327 * 4) glyph_to_swallow() does not return a showsyms[] index, but an 328 * offset from the first swallow symbol. If handed something 329 * out of range, it will return zero (for lack of anything better 330 * to return). 331 */ 332#define glyph_to_mon(glyph) \ 333 (glyph_is_normal_monster(glyph) ? ((glyph)-GLYPH_MON_OFF) : \ 334 glyph_is_pet(glyph) ? ((glyph)-GLYPH_PET_OFF) : \ 335 glyph_is_detected_monster(glyph) ? ((glyph)-GLYPH_DETECT_OFF) : \ 336 glyph_is_ridden_monster(glyph) ? ((glyph)-GLYPH_RIDDEN_OFF) : \ 337 NO_GLYPH) 338#define glyph_to_obj(glyph) \ 339 (glyph_is_body(glyph) ? CORPSE : \ 340 glyph_is_normal_object(glyph) ? ((glyph)-GLYPH_OBJ_OFF) : \ 341 NO_GLYPH) 342#define glyph_to_trap(glyph) \ 343 (glyph_is_trap(glyph) ? \ 344 ((int) defsym_to_trap((glyph) - GLYPH_CMAP_OFF)) : \ 345 NO_GLYPH) 346#define glyph_to_cmap(glyph) \ 347 (glyph_is_cmap(glyph) ? ((glyph) - GLYPH_CMAP_OFF) : \ 348 NO_GLYPH) 349#define glyph_to_swallow(glyph) \ 350 (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : \ 351 0) 352#define glyph_to_warning(glyph) \ 353 (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : \ 354 NO_GLYPH); 355 356/* 357 * Return true if the given glyph is what we want. Note that bodies are 358 * considered objects. 359 */ 360#define glyph_is_monster(glyph) \ 361 (glyph_is_normal_monster(glyph) \ 362 || glyph_is_pet(glyph) \ 363 || glyph_is_ridden_monster(glyph) \ 364 || glyph_is_detected_monster(glyph)) 365#define glyph_is_normal_monster(glyph) \ 366 ((glyph) >= GLYPH_MON_OFF && (glyph) < (GLYPH_MON_OFF+NUMMONS)) 367#define glyph_is_pet(glyph) \ 368 ((glyph) >= GLYPH_PET_OFF && (glyph) < (GLYPH_PET_OFF+NUMMONS)) 369#define glyph_is_body(glyph) \ 370 ((glyph) >= GLYPH_BODY_OFF && (glyph) < (GLYPH_BODY_OFF+NUMMONS)) 371#define glyph_is_ridden_monster(glyph) \ 372 ((glyph) >= GLYPH_RIDDEN_OFF && (glyph) < (GLYPH_RIDDEN_OFF+NUMMONS)) 373#define glyph_is_detected_monster(glyph) \ 374 ((glyph) >= GLYPH_DETECT_OFF && (glyph) < (GLYPH_DETECT_OFF+NUMMONS)) 375#define glyph_is_invisible(glyph) ((glyph) == GLYPH_INVISIBLE) 376#define glyph_is_normal_object(glyph) \ 377 ((glyph) >= GLYPH_OBJ_OFF && (glyph) < (GLYPH_OBJ_OFF+NUM_OBJECTS)) 378#define glyph_is_object(glyph) \ 379 (glyph_is_normal_object(glyph) \ 380 || glyph_is_body(glyph)) 381#define glyph_is_trap(glyph) \ 382 ((glyph) >= (GLYPH_CMAP_OFF+trap_to_defsym(1)) && \ 383 (glyph) < (GLYPH_CMAP_OFF+trap_to_defsym(1)+TRAPNUM)) 384#define glyph_is_cmap(glyph) \ 385 ((glyph) >= GLYPH_CMAP_OFF && (glyph) < (GLYPH_CMAP_OFF+MAXPCHARS)) 386#define glyph_is_swallow(glyph) \ 387 ((glyph) >= GLYPH_SWALLOW_OFF && (glyph) < (GLYPH_SWALLOW_OFF+(NUMMONS << 3))) 388#define glyph_is_warning(glyph) \ 389 ((glyph) >= GLYPH_WARNING_OFF && (glyph) < (GLYPH_WARNING_OFF + WARNCOUNT)) 390#endif /* DISPLAY_H */ 391