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. */
14 #include "mondata.h" /* for mindless() */
17 #ifndef INVISIBLE_OBJECTS
18 #define vobj_at(x,y) (level.objects[x][y])
24 * Returns true if the hero can sense the given monster. This includes
25 * monsters that are hiding or mimicing other monsters.
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 */\
33 (distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM)))) \
36 #define sensemon(mon) (tp_sensemon(mon) || Detect_monsters || MATCH_WARN_OF_MON(mon))
39 * mon_warning() is used to warn of any dangerous monsters in your
40 * vicinity, and a glyph representing the warning level is displayed.
43 #define mon_warning(mon) (Warning && !(mon)->mpeaceful && \
44 (distu((mon)->mx, (mon)->my) < 100) && \
45 (((int) ((mon)->m_lev / 4)) >= flags.warnlevel))
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.
55 #define mon_visible(mon) ( /* The hero can see 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 */\
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.
70 #define see_with_infrared(mon) (!Blind && Infravision && infravisible(mon->data) && couldsee(mon->mx, mon->my))
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.)
80 #define canseemon(mon) ((mon->wormno ? worm_known(mon) : \
81 (cansee(mon->mx, mon->my) || see_with_infrared(mon))) \
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
92 #define canspotmon(mon) \
93 (canseemon(mon) || sensemon(mon))
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.
106 #define knowninvisible(mon) \
108 ((cansee(mon->mx, mon->my) && (See_invisible || Detect_monsters)) || \
109 (!Blind && (HTelepat & ~INTRINSIC) && \
110 distu(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM) \
118 * A special case check used in attack() and domove(). Placing the
119 * definition here is convenient.
121 #define is_safepet(mon) \
122 (mon && mon->mtame && canspotmon(mon) && flags.safe_dog \
123 && !Confusion && !Hallucination && !Stunned)
130 * This returns true if the hero can see her/himself.
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.
135 #define canseeself() (Blind || u.uswallow || (!Invisible && !u.uundetected))
136 #define senseself() (canseeself() || Unblind_telepat || Detect_monsters)
143 * Respectively return a random monster, object, or trap number.
145 #define random_monster() rn2(NUMMONS)
146 #define random_object() rn1(NUM_OBJECTS-1,1)
147 #define random_trap() rn1(TRAPNUM-1,1)
154 * If hallucinating, choose a random object/monster, otherwise, use the one
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)
165 * These routines are true if what is really at the given location will
166 * "cover" any objects or traps that might be there.
168 #define covers_objects(xx,yy) \
169 ((is_pool(xx,yy) && !Underwater) || (levl[xx][yy].typ == LAVAPOOL))
171 #define covers_traps(xx,yy) covers_objects(xx,yy)
175 * tmp_at() control calls.
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. */
185 /* Total number of cmap indices in the sheild_static[] array. */
186 #define SHIELD_COUNT 21
192 * Display the hero. It is assumed that all checks necessary to determine
193 * _if_ the hero can be seen have already been done.
196 #define maybe_display_usteed (u.usteed && mon_visible(u.usteed)) ? \
197 ridden_mon_to_glyph(u.usteed) :
199 #define maybe_display_usteed /* empty */
202 #define display_self() \
203 show_glyph(u.ux, u.uy, \
204 maybe_display_usteed /* else */ \
205 youmonst.m_ap_type == M_AP_NOTHING ? \
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))
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.
223 * Glyphs are grouped for easy accessibility:
225 * monster Represents all the wild (not tame) monsters. Count: NUMMONS.
227 * pet Represents all of the tame monsters. Count: NUMMONS
229 * invisible Invisible monster placeholder. Count: 1
231 * detect Represents all detected monsters. Count: NUMMONS
233 * corpse One for each monster. Count: NUMMONS
235 * ridden Represents all monsters being ridden. Count: NUMMONS
237 * object One for each object. Count: NUM_OBJECTS
239 * cmap One for each entry in the character map. The character map
240 * is the dungeon features and other miscellaneous things.
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)
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
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
257 * warning A set of six representing the different warning levels.
259 * The following are offsets used to convert to and from a glyph.
261 #define NUM_ZAP 8 /* number of zap beam types */
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)
277 #define NO_GLYPH MAX_GLYPH
279 #define GLYPH_INVISIBLE GLYPH_INVIS_OFF
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)
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) \
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))
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)
302 #define trap_to_glyph(trap) \
303 cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp)))
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)
312 /* The hero's glyph when seen as a monster.
315 monnum_to_glyph((Upolyd || !iflags.showrace) ? u.umonnum : \
316 (flags.female && urace.femalenum != NON_PM) ? urace.femalenum : \
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
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) : \
338 #define glyph_to_obj(glyph) \
339 (glyph_is_body(glyph) ? CORPSE : \
340 glyph_is_normal_object(glyph) ? ((glyph)-GLYPH_OBJ_OFF) : \
342 #define glyph_to_trap(glyph) \
343 (glyph_is_trap(glyph) ? \
344 ((int) defsym_to_trap((glyph) - GLYPH_CMAP_OFF)) : \
346 #define glyph_to_cmap(glyph) \
347 (glyph_is_cmap(glyph) ? ((glyph) - GLYPH_CMAP_OFF) : \
349 #define glyph_to_swallow(glyph) \
350 (glyph_is_swallow(glyph) ? (((glyph) - GLYPH_SWALLOW_OFF) & 0x7) : \
352 #define glyph_to_warning(glyph) \
353 (glyph_is_warning(glyph) ? ((glyph) - GLYPH_WARNING_OFF) : \
357 * Return true if the given glyph is what we want. Note that bodies are
358 * considered objects.
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 */