1 | /* SCCS Id: @(#)display.h 3.3 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 | * 129 | * This returns true if the hero can see her/himself. 130 | * 131 | * The u.uswallow check assumes that you can see yourself even if you are 132 | * invisible. If not, then we don't need the check. 133 | */ 134 | #define canseeself() (Blind || u.uswallow || (!Invisible && !u.uundetected)) 135 | 136 | 137 | /* 138 | * random_monster() 139 | * random_object() 140 | * random_trap() 141 | * 142 | * Respectively return a random monster, object, or trap number. 143 | */ 144 | #define random_monster() rn2(NUMMONS) 145 | #define random_object() rn1(NUM_OBJECTS-1,1) 146 | #define random_trap() rn1(TRAPNUM-1,1) 147 | 148 | /* 149 | * what_obj() 150 | * what_mon() 151 | * what_trap() 152 | * 153 | * If hallucinating, choose a random object/monster, otherwise, use the one 154 | * given. 155 | */ 156 | #define what_obj(obj) (Hallucination ? random_object() : obj) 157 | #define what_mon(mon) (Hallucination ? random_monster() : mon) 158 | #define what_trap(trp) (Hallucination ? random_trap() : trp) 159 | 160 | /* 161 | * covers_objects() 162 | * covers_traps() 163 | * 164 | * These routines are true if what is really at the given location will 165 | * "cover" any objects or traps that might be there. 166 | */ 167 | #define covers_objects(xx,yy) \ 168 | ((is_pool(xx,yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL)) 169 | 170 | #define covers_traps(xx,yy) covers_objects(xx,yy) 171 | 172 | 173 | /* 174 | * tmp_at() control calls. 175 | */ 176 | #define DISP_BEAM (-1) /* Keep all glyphs showing & clean up at end. */ 177 | #define DISP_FLASH (-2) /* Clean up each glyph before displaying new one. */ 178 | #define DISP_ALWAYS (-3) /* Like flash, but still displayed if not visible. */ 179 | #define DISP_CHANGE (-4) /* Change glyph. */ 180 | #define DISP_END (-5) /* Clean up. */ 181 | #define DISP_FREEMEM (-6) /* Free all memory during exit only. */ 182 | 183 | 184 | /* Total number of cmap indices in the sheild_static[] array. */ 185 | #define SHIELD_COUNT 21 186 | 187 | 188 | /* 189 | * display_self() 190 | * 191 | * Display the hero. It is assumed that all checks necessary to determine 192 | * _if_ the hero can be seen have already been done. 193 | */ 194 | #ifdef STEED 195 | #define display_self() \ 196 | show_glyph(u.ux, u.uy, \ 197 | (u.usteed && mon_visible(u.usteed)) ? \ 198 | ridden_mon_to_glyph(u.usteed) : \ 199 | youmonst.m_ap_type == M_AP_NOTHING ? \ 200 | hero_glyph : \ 201 | youmonst.m_ap_type == M_AP_FURNITURE ? \ 202 | cmap_to_glyph(youmonst.mappearance) : \ 203 | youmonst.m_ap_type == M_AP_OBJECT ? \ 204 | objnum_to_glyph(youmonst.mappearance) : \ 205 | /* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance)) 206 | #else 207 | #define display_self() \ 208 | show_glyph(u.ux, u.uy, \ 209 | youmonst.m_ap_type == M_AP_NOTHING ? \ 210 | hero_glyph : \ 211 | youmonst.m_ap_type == M_AP_FURNITURE ? \ 212 | cmap_to_glyph(youmonst.mappearance) : \ 213 | youmonst.m_ap_type == M_AP_OBJECT ? \ 214 | objnum_to_glyph(youmonst.mappearance) : \ 215 | /* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance)) 216 | #endif 217 | 218 | /* 219 | * A glyph is an abstraction that represents a _unique_ monster, object, 220 | * dungeon part, or effect. The uniqueness is important. For example, 221 | * It is not enough to have four (one for each "direction") zap beam glyphs, 222 | * we need a set of four for each beam type. Why go to so much trouble? 223 | * Because it is possible that any given window dependent display driver 224 | * [print_glyph()] can produce something different for each type of glyph. 225 | * That is, a beam of cold and a beam of fire would not only be different 226 | * colors, but would also be represented by different symbols. 227 | * 228 | * Glyphs are grouped for easy accessibility: 229 | * 230 | * monster Represents all the wild (not tame) monsters. Count: NUMMONS. 231 | * 232 | * pet Represents all of the tame monsters. Count: NUMMONS 233 | * 234 | * invisible Invisible monster placeholder. Count: 1 235 | * 236 | * detect Represents all detected monsters. Count: NUMMONS 237 | * 238 | * corpse One for each monster. Count: NUMMONS 239 | * 240 | * ridden Represents all monsters being ridden. Count: NUMMONS 241 | * 242 | * object One for each object. Count: NUM_OBJECTS 243 | * 244 | * cmap One for each entry in the character map. The character map 245 | * is the dungeon features and other miscellaneous things. 246 | * Count: MAXPCHARS 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_ZAP_OFF (MAXPCHARS + GLYPH_CMAP_OFF) 272 | #define GLYPH_SWALLOW_OFF ((NUM_ZAP << 2) + GLYPH_ZAP_OFF) 273 | #define GLYPH_WARNING_OFF ((NUMMONS << 3) + GLYPH_SWALLOW_OFF) 274 | #define MAX_GLYPH (WARNCOUNT + GLYPH_WARNING_OFF) 275 | 276 | #define NO_GLYPH MAX_GLYPH 277 | 278 | #define GLYPH_INVISIBLE GLYPH_INVIS_OFF 279 | 280 | #define warning_to_glyph(mwarnlev) ((mwarnlev)+GLYPH_WARNING_OFF) 281 | #define mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_MON_OFF) 282 | #define detected_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_DETECT_OFF) 283 | #define ridden_mon_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_RIDDEN_OFF) 284 | #define pet_to_glyph(mon) ((int) what_mon(monsndx((mon)->data))+GLYPH_PET_OFF) 285 | 286 | /* This has the unfortunate side effect of needing a global variable */ 287 | /* to store a result. 'otg_temp' is defined and declared in decl.{ch}. */ 288 | #define obj_to_glyph(obj) \ 289 | (Hallucination ? \ 290 | ((otg_temp = random_object()) == CORPSE ? \ 291 | random_monster() + GLYPH_BODY_OFF : \ 292 | otg_temp + GLYPH_OBJ_OFF) : \ 293 | ((obj)->otyp == CORPSE ? \ 294 | (int) (obj)->corpsenm + GLYPH_BODY_OFF : \ 295 | (int) (obj)->otyp + GLYPH_OBJ_OFF)) 296 | 297 | #define cmap_to_glyph(cmap_idx) ((int) (cmap_idx) + GLYPH_CMAP_OFF) 298 | #define trap_to_glyph(trap) \ 299 | cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp))) 300 | 301 | /* Not affected by hallucination. Gives a generic body for CORPSE */ 302 | #define objnum_to_glyph(onum) ((int) (onum) + GLYPH_OBJ_OFF) 303 | #define monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_MON_OFF) 304 | #define detected_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_DETECT_OFF) 305 | #define ridden_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_RIDDEN_OFF) 306 | #define petnum_to_glyph(mnum) ((int) (mnum) + GLYPH_PET_OFF) 307 | 308 | /* The hero's glyph when seen as a monster. Could also be... 309 | * mon_to_glyph(Upolyd || Race_if(PM_HUMAN) ? u.umonnum : urace.malenum) 310 | */ 311 | #define hero_glyph monnum_to_glyph(u.umonnum) 312 | 313 | 314 | /* 315 | * Change the given glyph into it's given type. Note: 316 | * 1) Pets, detected, and ridden monsters are animals and are converted 317 | * to the proper monster number. 318 | * 2) Bodies are all mapped into the generic CORPSE object 319 | * 3) If handed a glyph out of range for the type, these functions 320 | * will return NO_GLYPH (see exception below) 321 | * 4) glyph_to_swallow() does not return a showsyms[] index, but an 322 | * offset from the first swallow symbol. If handed something 323 | * out of range, it will return zero (for lack of anything better 324 | * to return). 325 | */ 326 | #define glyph_to_mon(glyph) \ 327 | (glyph_is_normal_monster(glyph) ? ((glyph)-GLYPH_MON_OFF) : \ 328 | glyph_is_pet(glyph) ? ((glyph)-GLYPH_PET_OFF) : \ 329 | glyph_is_detected_monster(glyph) ? ((glyph)-GLYPH_DETECT_OFF) : \ 330 | glyph_is_ridden_monster(glyph) ? ((glyph)-GLYPH_RIDDEN_OFF) : \ 331 | NO_GLYPH) 332 | #define glyph_to_obj(glyph) \ 333 | (glyph_is_body(glyph) ? CORPSE : \ 334 | glyph_is_normal_object(glyph) ? ((glyph)-GLYPH_OBJ_OFF) : \ 335 | NO_GLYPH) 336 | #define glyph_to_trap(glyph) \ 337 | (glyph_is_trap(glyph) ? \ 338 | ((int) defsym_to_trap((glyph) - GLYPH_CMAP_OFF)) : \ 339 | NO_GLYPH) 340 | #define glyph_to_cmap(glyph) \ 341 | (glyph_is_cmap(glyph) ? ((glyph) - GLYPH_CMAP_OFF) : \ 342 | NO_GLYPH) 343 | #define glyph_to_swallow(glyph) \ 344 | (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : \ 345 | 0) 346 | #define glyph_to_warning(glyph) \ 347 | (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : \ 348 | NO_GLYPH); 349 | 350 | /* 351 | * Return true if the given glyph is what we want. Note that bodies are 352 | * considered objects. 353 | */ 354 | #define glyph_is_monster(glyph) \ 355 | (glyph_is_normal_monster(glyph) \ 356 | || glyph_is_pet(glyph) \ 357 | || glyph_is_ridden_monster(glyph) \ 358 | || glyph_is_detected_monster(glyph)) 359 | #define glyph_is_normal_monster(glyph) \ 360 | ((glyph) >= GLYPH_MON_OFF && (glyph) < (GLYPH_MON_OFF+NUMMONS)) 361 | #define glyph_is_pet(glyph) \ 362 | ((glyph) >= GLYPH_PET_OFF && (glyph) < (GLYPH_PET_OFF+NUMMONS)) 363 | #define glyph_is_body(glyph) \ 364 | ((glyph) >= GLYPH_BODY_OFF && (glyph) < (GLYPH_BODY_OFF+NUMMONS)) 365 | #define glyph_is_ridden_monster(glyph) \ 366 | ((glyph) >= GLYPH_RIDDEN_OFF && (glyph) < (GLYPH_RIDDEN_OFF+NUMMONS)) 367 | #define glyph_is_detected_monster(glyph) \ 368 | ((glyph) >= GLYPH_DETECT_OFF && (glyph) < (GLYPH_DETECT_OFF+NUMMONS)) 369 | #define glyph_is_invisible(glyph) ((glyph) == GLYPH_INVISIBLE) 370 | #define glyph_is_normal_object(glyph) \ 371 | ((glyph) >= GLYPH_OBJ_OFF && (glyph) < (GLYPH_OBJ_OFF+NUM_OBJECTS)) 372 | #define glyph_is_object(glyph) \ 373 | (glyph_is_normal_object(glyph) \ 374 | || glyph_is_body(glyph)) 375 | #define glyph_is_trap(glyph) \ 376 | ((glyph) >= (GLYPH_CMAP_OFF+trap_to_defsym(1)) && \ 377 | (glyph) < (GLYPH_CMAP_OFF+trap_to_defsym(1)+TRAPNUM)) 378 | #define glyph_is_cmap(glyph) \ 379 | ((glyph) >= GLYPH_CMAP_OFF && (glyph) < (GLYPH_CMAP_OFF+MAXPCHARS)) 380 | #define glyph_is_swallow(glyph) \ 381 | ((glyph) >= GLYPH_SWALLOW_OFF && (glyph) < (GLYPH_SWALLOW_OFF+(NUMMONS << 3))) 382 | #define glyph_is_warning(glyph) \ 383 | ((glyph) >= GLYPH_WARNING_OFF && (glyph) < (GLYPH_WARNING_OFF + WARNCOUNT)) 384 | #endif /* DISPLAY_H */