1 /* NetHack 3.6 display.h $NHDT-Date: 1559994621 2019/06/08 11:50:21 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.32 $ */
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. */
13 #include "mondata.h" /* for mindless() */
19 * Returns the head of the list of objects that the player can see
22 #define vobj_at(x, y) (level.objects[x][y])
27 * Returns true if the hero can sense the given monster. This includes
28 * monsters that are hiding or mimicing other monsters.
30 #define tp_sensemon(mon) \
31 (/* The hero can always sense a monster IF: */ \
32 /* 1. the monster has a brain to sense */ \
33 (!mindless(mon->data)) \
34 /* AND 2a. hero is blind and telepathic */ \
35 && ((Blind && Blind_telepat) \
36 /* OR 2b. hero is using a telepathy inducing */ \
37 /* object and in range */ \
39 && (distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM)))))
41 #define sensemon(mon) \
42 (tp_sensemon(mon) || Detect_monsters || MATCH_WARN_OF_MON(mon))
45 * mon_warning() is used to warn of any dangerous monsters in your
46 * vicinity, and a glyph representing the warning level is displayed.
49 #define mon_warning(mon) \
50 (Warning && !(mon)->mpeaceful && (distu((mon)->mx, (mon)->my) < 100) \
51 && (((int) ((mon)->m_lev / 4)) >= context.warnlevel))
56 * Returns true if the hero can see the monster. It is assumed that the
57 * hero can physically see the location of the monster. The function
58 * vobj_at() returns a pointer to an object that the hero can see there.
59 * Infravision is not taken into account.
62 #define mon_visible(mon) \
63 (/* The hero can see the monster IF the monster */ \
64 (!mon->minvis || See_invisible) /* 1. is not invisible */ \
65 && !mon->mundetected /* AND 2. not an undetected hider */ \
66 && !(mon->mburied || u.uburied)) /* AND 3. neither you nor it is buried */
67 #else /* without 'mburied' and 'uburied' */
68 #define mon_visible(mon) \
69 (/* The hero can see the monster IF the monster */ \
70 (!mon->minvis || See_invisible) /* 1. is not invisible */ \
71 && !mon->mundetected) /* AND 2. not an undetected hider */
77 * This function is true if the player can see a monster using infravision.
78 * The caller must check for invisibility (invisible monsters are also
79 * invisible to infravision), because this is usually called from within
80 * canseemon() or canspotmon() which already check that.
82 #define see_with_infrared(mon) \
83 (!Blind && Infravision && mon && infravisible(mon->data) \
84 && couldsee(mon->mx, mon->my))
89 * This is the globally used canseemon(). It is not called within the display
90 * routines. Like mon_visible(), but it checks to see if the hero sees the
91 * location instead of assuming it. (And also considers worms.)
93 #define canseemon(mon) \
94 ((mon->wormno ? worm_known(mon) \
95 : (cansee(mon->mx, mon->my) || see_with_infrared(mon))) \
101 * This function checks whether you can either see a monster or sense it by
102 * telepathy, and is what you usually call for monsters about which nothing is
105 #define canspotmon(mon) (canseemon(mon) || sensemon(mon))
107 /* knowninvisible(mon)
108 * This one checks to see if you know a monster is both there and invisible.
109 * 1) If you can see the monster and have see invisible, it is assumed the
110 * monster is transparent, but visible in some manner. (Earlier versions of
111 * Nethack were really inconsistent on this.)
112 * 2) If you can't see the monster, but can see its location and you have
113 * telepathy that works when you can see, you can tell that there is a
114 * creature in an apparently empty spot.
115 * Infravision is not relevant; we assume that invisible monsters are also
116 * invisible to infravision.
118 #define knowninvisible(mon) \
120 && ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) \
121 || (!Blind && (HTelepat & ~INTRINSIC) \
122 && distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM))))
127 * A special case check used in attack() and domove(). Placing the
128 * definition here is convenient.
130 #define is_safepet(mon) \
131 (mon && mon->mtame && canspotmon(mon) && flags.safe_dog && !Confusion \
132 && !Hallucination && !Stunned)
139 * This returns true if the hero can see her/himself.
141 * Sensing yourself by touch is treated as seeing yourself, even if
142 * unable to see. So when blind, being invisible won't affect your
143 * self-perception, and when swallowed, the enclosing monster touches.
145 #define canseeself() (Blind || u.uswallow || (!Invisible && !u.uundetected))
146 #define senseself() (Unblind_telepat || Detect_monsters)
147 #define canspotself() (canseeself() || senseself())
154 * Respectively return a random monster, object, or trap number.
156 #define random_monster(rng) rng(NUMMONS)
157 #define random_object(rng) (rng(NUM_OBJECTS - 1) + 1)
158 #define random_trap(rng) (rng(TRAPNUM - 1) + 1)
165 * If hallucinating, choose a random object/monster, otherwise, use the one
166 * given. Use the given rng to handle hallucination.
168 #define what_obj(obj, rng) (Hallucination ? random_object(rng) : obj)
169 #define what_mon(mon, rng) (Hallucination ? random_monster(rng) : mon)
170 #define what_trap(trp, rng) (Hallucination ? random_trap(rng) : trp)
175 * An appropriate random number generator for use with newsym(), when
176 * randomness is needed there. This is currently hardcoded as
177 * rn2_on_display_rng, but is futureproofed for cases where we might
178 * want to prevent display-random objects entering the character's
179 * memory (this isn't important at present but may be if we need
180 * reproducible gameplay for some reason).
182 #define newsym_rn2 rn2_on_display_rng
188 * These routines are true if what is really at the given location will
189 * "cover" any objects or traps that might be there.
191 #define covers_objects(xx, yy) \
192 ((is_pool(xx, yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL))
194 #define covers_traps(xx, yy) covers_objects(xx, yy)
197 * tmp_at() control calls.
199 #define DISP_BEAM (-1) /* Keep all glyphs showing & clean up at end. */
200 #define DISP_ALL (-2) /* Like beam, but still displayed if not visible. */
201 #define DISP_TETHER (-3) /* Like beam, but tether glyph differs from final */
202 #define DISP_FLASH (-4) /* Clean up each glyph before displaying new one. */
203 #define DISP_ALWAYS (-5) /* Like flash, but still displayed if not visible. */
204 #define DISP_CHANGE (-6) /* Change glyph. */
205 #define DISP_END (-7) /* Clean up. */
206 #define DISP_FREEMEM (-8) /* Free all memory during exit only. */
208 /* Total number of cmap indices in the shield_static[] array. */
209 #define SHIELD_COUNT 21
210 #define BACKTRACK (-1) /* flag for DISP_END to display each prior location */
215 * Display the hero. It is assumed that all checks necessary to determine
216 * _if_ the hero can be seen have already been done.
218 #define maybe_display_usteed(otherwise_self) \
219 ((u.usteed && mon_visible(u.usteed)) \
220 ? ridden_mon_to_glyph(u.usteed, rn2_on_display_rng) \
223 #define display_self() \
224 show_glyph(u.ux, u.uy, \
225 maybe_display_usteed((U_AP_TYPE == M_AP_NOTHING) \
227 : (U_AP_TYPE == M_AP_FURNITURE) \
228 ? cmap_to_glyph(youmonst.mappearance) \
229 : (U_AP_TYPE == M_AP_OBJECT) \
230 ? objnum_to_glyph(youmonst.mappearance) \
231 /* else U_AP_TYPE == M_AP_MONSTER */ \
232 : monnum_to_glyph(youmonst.mappearance)))
235 * A glyph is an abstraction that represents a _unique_ monster, object,
236 * dungeon part, or effect. The uniqueness is important. For example,
237 * It is not enough to have four (one for each "direction") zap beam glyphs,
238 * we need a set of four for each beam type. Why go to so much trouble?
239 * Because it is possible that any given window dependent display driver
240 * [print_glyph()] can produce something different for each type of glyph.
241 * That is, a beam of cold and a beam of fire would not only be different
242 * colors, but would also be represented by different symbols.
244 * Glyphs are grouped for easy accessibility:
246 * monster Represents all the wild (not tame) monsters. Count: NUMMONS.
248 * pet Represents all of the tame monsters. Count: NUMMONS
250 * invisible Invisible monster placeholder. Count: 1
252 * detect Represents all detected monsters. Count: NUMMONS
254 * corpse One for each monster. Count: NUMMONS
256 * ridden Represents all monsters being ridden. Count: NUMMONS
258 * object One for each object. Count: NUM_OBJECTS
260 * cmap One for each entry in the character map. The character map
261 * is the dungeon features and other miscellaneous things.
264 * explosions A set of nine for each of the following seven explosion types:
265 * dark, noxious, muddy, wet, magical, fiery, frosty.
266 * The nine positions represent those surrounding the hero.
267 * Count: MAXEXPCHARS * EXPL_MAX (EXPL_MAX is defined in hack.h)
269 * zap beam A set of four (there are four directions) for each beam type.
270 * The beam type is shifted over 2 positions and the direction
271 * is stored in the lower 2 bits. Count: NUM_ZAP << 2
273 * swallow A set of eight for each monster. The eight positions rep-
274 * resent those surrounding the hero. The monster number is
275 * shifted over 3 positions and the swallow position is stored
276 * in the lower three bits. Count: NUMMONS << 3
278 * warning A set of six representing the different warning levels.
280 * statue One for each monster. Count: NUMMONS
282 * The following are offsets used to convert to and from a glyph.
284 #define NUM_ZAP 8 /* number of zap beam types */
286 #define GLYPH_MON_OFF 0
287 #define GLYPH_PET_OFF (NUMMONS + GLYPH_MON_OFF)
288 #define GLYPH_INVIS_OFF (NUMMONS + GLYPH_PET_OFF)
289 #define GLYPH_DETECT_OFF (1 + GLYPH_INVIS_OFF)
290 #define GLYPH_BODY_OFF (NUMMONS + GLYPH_DETECT_OFF)
291 #define GLYPH_RIDDEN_OFF (NUMMONS + GLYPH_BODY_OFF)
292 #define GLYPH_OBJ_OFF (NUMMONS + GLYPH_RIDDEN_OFF)
293 #define GLYPH_CMAP_OFF (NUM_OBJECTS + GLYPH_OBJ_OFF)
294 #define GLYPH_EXPLODE_OFF ((MAXPCHARS - MAXEXPCHARS) + GLYPH_CMAP_OFF)
295 #define GLYPH_ZAP_OFF ((MAXEXPCHARS * EXPL_MAX) + GLYPH_EXPLODE_OFF)
296 #define GLYPH_SWALLOW_OFF ((NUM_ZAP << 2) + GLYPH_ZAP_OFF)
297 #define GLYPH_WARNING_OFF ((NUMMONS << 3) + GLYPH_SWALLOW_OFF)
298 #define GLYPH_STATUE_OFF (WARNCOUNT + GLYPH_WARNING_OFF)
299 #define MAX_GLYPH (NUMMONS + GLYPH_STATUE_OFF)
301 #define NO_GLYPH MAX_GLYPH
302 #define GLYPH_INVISIBLE GLYPH_INVIS_OFF
304 #define warning_to_glyph(mwarnlev) ((mwarnlev) + GLYPH_WARNING_OFF)
305 #define mon_to_glyph(mon, rng) \
306 ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_MON_OFF)
307 #define detected_mon_to_glyph(mon, rng) \
308 ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_DETECT_OFF)
309 #define ridden_mon_to_glyph(mon, rng) \
310 ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_RIDDEN_OFF)
311 #define pet_to_glyph(mon, rng) \
312 ((int) what_mon(monsndx((mon)->data), rng) + GLYPH_PET_OFF)
314 /* This has the unfortunate side effect of needing a global variable */
315 /* to store a result. 'otg_temp' is defined and declared in decl.{ch}. */
316 #define random_obj_to_glyph(rng) \
317 ((otg_temp = random_object(rng)) == CORPSE \
318 ? random_monster(rng) + GLYPH_BODY_OFF \
319 : otg_temp + GLYPH_OBJ_OFF)
321 #define obj_to_glyph(obj, rng) \
322 (((obj)->otyp == STATUE) \
323 ? statue_to_glyph(obj, rng) \
325 ? random_obj_to_glyph(rng) \
326 : ((obj)->otyp == CORPSE) \
327 ? (int) (obj)->corpsenm + GLYPH_BODY_OFF \
328 : (int) (obj)->otyp + GLYPH_OBJ_OFF)
330 /* MRKR: Statues now have glyphs corresponding to the monster they */
331 /* represent and look like monsters when you are hallucinating. */
333 #define statue_to_glyph(obj, rng) \
334 (Hallucination ? random_monster(rng) + GLYPH_MON_OFF \
335 : (int) (obj)->corpsenm + GLYPH_STATUE_OFF)
337 #define cmap_to_glyph(cmap_idx) ((int) (cmap_idx) + GLYPH_CMAP_OFF)
338 #define explosion_to_glyph(expltype, idx) \
339 ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF)
341 #define trap_to_glyph(trap, rng) \
342 cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp, rng)))
344 /* Not affected by hallucination. Gives a generic body for CORPSE */
345 /* MRKR: ...and the generic statue */
346 #define objnum_to_glyph(onum) ((int) (onum) + GLYPH_OBJ_OFF)
347 #define monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_MON_OFF)
348 #define detected_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_DETECT_OFF)
349 #define ridden_monnum_to_glyph(mnum) ((int) (mnum) + GLYPH_RIDDEN_OFF)
350 #define petnum_to_glyph(mnum) ((int) (mnum) + GLYPH_PET_OFF)
352 /* The hero's glyph when seen as a monster.
355 monnum_to_glyph((Upolyd || !flags.showrace) \
357 : (flags.female && urace.femalenum != NON_PM) \
362 * Change the given glyph into it's given type. Note:
363 * 1) Pets, detected, and ridden monsters are animals and are converted
364 * to the proper monster number.
365 * 2) Bodies are all mapped into the generic CORPSE object
366 * 3) If handed a glyph out of range for the type, these functions
367 * will return NO_GLYPH (see exception below)
368 * 4) glyph_to_swallow() does not return a showsyms[] index, but an
369 * offset from the first swallow symbol. If handed something
370 * out of range, it will return zero (for lack of anything better
373 #define glyph_to_mon(glyph) \
374 (glyph_is_normal_monster(glyph) \
375 ? ((glyph) - GLYPH_MON_OFF) \
376 : glyph_is_pet(glyph) \
377 ? ((glyph) - GLYPH_PET_OFF) \
378 : glyph_is_detected_monster(glyph) \
379 ? ((glyph) - GLYPH_DETECT_OFF) \
380 : glyph_is_ridden_monster(glyph) \
381 ? ((glyph) - GLYPH_RIDDEN_OFF) \
382 : glyph_is_statue(glyph) \
383 ? ((glyph) - GLYPH_STATUE_OFF) \
385 #define glyph_to_obj(glyph) \
386 (glyph_is_body(glyph) \
388 : glyph_is_statue(glyph) \
390 : glyph_is_normal_object(glyph) \
391 ? ((glyph) - GLYPH_OBJ_OFF) \
393 #define glyph_to_trap(glyph) \
394 (glyph_is_trap(glyph) ? ((int) defsym_to_trap((glyph) - GLYPH_CMAP_OFF)) \
396 #define glyph_to_cmap(glyph) \
397 (glyph_is_cmap(glyph) ? ((glyph) - GLYPH_CMAP_OFF) : NO_GLYPH)
398 #define glyph_to_swallow(glyph) \
399 (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : 0)
400 #define glyph_to_warning(glyph) \
401 (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : NO_GLYPH);
404 * Return true if the given glyph is what we want. Note that bodies are
405 * considered objects.
407 #define glyph_is_monster(glyph) \
408 (glyph_is_normal_monster(glyph) || glyph_is_pet(glyph) \
409 || glyph_is_ridden_monster(glyph) || glyph_is_detected_monster(glyph))
410 #define glyph_is_normal_monster(glyph) \
411 ((glyph) >= GLYPH_MON_OFF && (glyph) < (GLYPH_MON_OFF + NUMMONS))
412 #define glyph_is_pet(glyph) \
413 ((glyph) >= GLYPH_PET_OFF && (glyph) < (GLYPH_PET_OFF + NUMMONS))
414 #define glyph_is_body(glyph) \
415 ((glyph) >= GLYPH_BODY_OFF && (glyph) < (GLYPH_BODY_OFF + NUMMONS))
417 #define glyph_is_statue(glyph) \
418 ((glyph) >= GLYPH_STATUE_OFF && (glyph) < (GLYPH_STATUE_OFF + NUMMONS))
420 #define glyph_is_ridden_monster(glyph) \
421 ((glyph) >= GLYPH_RIDDEN_OFF && (glyph) < (GLYPH_RIDDEN_OFF + NUMMONS))
422 #define glyph_is_detected_monster(glyph) \
423 ((glyph) >= GLYPH_DETECT_OFF && (glyph) < (GLYPH_DETECT_OFF + NUMMONS))
424 #define glyph_is_invisible(glyph) ((glyph) == GLYPH_INVISIBLE)
425 #define glyph_is_normal_object(glyph) \
426 ((glyph) >= GLYPH_OBJ_OFF && (glyph) < (GLYPH_OBJ_OFF + NUM_OBJECTS))
427 #define glyph_is_object(glyph) \
428 (glyph_is_normal_object(glyph) || glyph_is_statue(glyph) \
429 || glyph_is_body(glyph))
430 #define glyph_is_trap(glyph) \
431 ((glyph) >= (GLYPH_CMAP_OFF + trap_to_defsym(1)) \
432 && (glyph) < (GLYPH_CMAP_OFF + trap_to_defsym(1) + TRAPNUM))
433 #define glyph_is_cmap(glyph) \
434 ((glyph) >= GLYPH_CMAP_OFF && (glyph) < (GLYPH_CMAP_OFF + MAXPCHARS))
435 #define glyph_is_swallow(glyph) \
436 ((glyph) >= GLYPH_SWALLOW_OFF \
437 && (glyph) < (GLYPH_SWALLOW_OFF + (NUMMONS << 3)))
438 #define glyph_is_warning(glyph) \
439 ((glyph) >= GLYPH_WARNING_OFF \
440 && (glyph) < (GLYPH_WARNING_OFF + WARNCOUNT))
442 #endif /* DISPLAY_H */