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