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 */