1/*	SCCS Id: @(#)mapglyph.c	3.4	2003/01/08	*/
2/* Copyright (c) David Cohrs, 1991				  */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6#if defined(TTY_GRAPHICS)
7#include "wintty.h"	/* for prototype of has_color() only */
8#endif
9#include "color.h"
10#define HI_DOMESTIC CLR_WHITE	/* monst.c */
11
12int explcolors[] = {
13	CLR_BLACK,	/* dark    */
14	CLR_GREEN,	/* noxious */
15	CLR_BROWN,	/* muddy   */
16	CLR_BLUE,	/* wet     */
17	CLR_MAGENTA,	/* magical */
18	CLR_ORANGE,	/* fiery   */
19	CLR_WHITE,	/* frosty  */
20};
21
22#if !defined(TTY_GRAPHICS)
23#define has_color(n)  TRUE
24#endif
25
26#ifdef TEXTCOLOR
27#define zap_color(n)  color = iflags.use_color ? zapcolors[n] : NO_COLOR
28#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR
29#define obj_color(n)  color = iflags.use_color ? objects[n].oc_color : NO_COLOR
30#define mon_color(n)  color = iflags.use_color ? mons[n].mcolor : NO_COLOR
31#define invis_color(n) color = NO_COLOR
32#define pet_color(n)  color = iflags.use_color ? mons[n].mcolor : NO_COLOR
33#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
34#define explode_color(n) color = iflags.use_color ? explcolors[n] : NO_COLOR
35# if defined(REINCARNATION) && defined(ASCIIGRAPH)
36#  define ROGUE_COLOR
37# endif
38
39#else	/* no text color */
40
41#define zap_color(n)
42#define cmap_color(n)
43#define obj_color(n)
44#define mon_color(n)
45#define invis_color(n)
46#define pet_color(c)
47#define warn_color(n)
48#define explode_color(n)
49#endif
50
51#ifdef ROGUE_COLOR
52# if defined(USE_TILES) && defined(MSDOS)
53#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && !iflags.grmode && \
54	Is_rogue_level(&u.uz))
55# else
56#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && Is_rogue_level(&u.uz))
57# endif
58#endif
59
60/*ARGSUSED*/
61void
62mapglyph(glyph, ochar, ocolor, ospecial, x, y)
63int glyph, *ocolor, x, y;
64int *ochar;
65unsigned *ospecial;
66{
67	register int offset;
68#if defined(TEXTCOLOR) || defined(ROGUE_COLOR)
69	int color = NO_COLOR;
70#endif
71	uchar ch;
72	unsigned special = 0;
73
74    /*
75     *  Map the glyph back to a character and color.
76     *
77     *  Warning:  For speed, this makes an assumption on the order of
78     *		  offsets.  The order is set in display.h.
79     */
80    if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) {	/* a warning flash */
81    	ch = warnsyms[offset];
82# ifdef ROGUE_COLOR
83	if (HAS_ROGUE_IBM_GRAPHICS)
84	    color = NO_COLOR;
85	else
86# endif
87	    warn_color(offset);
88    } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {	/* swallow */
89	/* see swallow_to_glyph() in display.c */
90	ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)];
91#ifdef ROGUE_COLOR
92	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color)
93	    color = NO_COLOR;
94	else
95#endif
96	    mon_color(offset >> 3);
97    } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {	/* zap beam */
98	/* see zapdir_to_glyph() in display.c */
99	ch = showsyms[S_vbeam + (offset & 0x3)];
100#ifdef ROGUE_COLOR
101	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color)
102	    color = NO_COLOR;
103	else
104#endif
105	    zap_color((offset >> 2));
106    } else if ((offset = (glyph - GLYPH_EXPLODE_OFF)) >= 0) {	/* explosion */
107	ch = showsyms[(offset % MAXEXPCHARS) + S_explode1];
108	explode_color(offset / MAXEXPCHARS);
109    } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) {	/* cmap */
110	ch = showsyms[offset];
111#ifdef ROGUE_COLOR
112	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) {
113	    if (offset >= S_vwall && offset <= S_hcdoor)
114		color = CLR_BROWN;
115	    else if (offset >= S_arrow_trap && offset <= S_polymorph_trap)
116		color = CLR_MAGENTA;
117	    else if (offset == S_corr || offset == S_litcorr)
118		color = CLR_GRAY;
119	    else if (offset >= S_room && offset <= S_water)
120		color = CLR_GREEN;
121	    else
122		color = NO_COLOR;
123	} else
124#endif
125#ifdef TEXTCOLOR
126	    /* provide a visible difference if normal and lit corridor
127	     * use the same symbol */
128	    if (iflags.use_color &&
129		offset == S_litcorr && ch == showsyms[S_corr])
130		color = CLR_WHITE;
131	    else
132#endif
133	    cmap_color(offset);
134    } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {	/* object */
135	if (offset == BOULDER && iflags.bouldersym) ch = iflags.bouldersym;
136	else ch = oc_syms[(int)objects[offset].oc_class];
137#ifdef ROGUE_COLOR
138	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) {
139	    switch(objects[offset].oc_class) {
140		case COIN_CLASS: color = CLR_YELLOW; break;
141		case FOOD_CLASS: color = CLR_RED; break;
142		default: color = CLR_BRIGHT_BLUE; break;
143	    }
144	} else
145#endif
146	    obj_color(offset);
147    } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) {	/* mon ridden */
148	ch = monsyms[(int)mons[offset].mlet];
149#ifdef ROGUE_COLOR
150	if (HAS_ROGUE_IBM_GRAPHICS)
151	    /* This currently implies that the hero is here -- monsters */
152	    /* don't ride (yet...).  Should we set it to yellow like in */
153	    /* the monster case below?  There is no equivalent in rogue. */
154	    color = NO_COLOR;	/* no need to check iflags.use_color */
155	else
156#endif
157	    mon_color(offset);
158	    special |= MG_RIDDEN;
159    } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {	/* a corpse */
160	ch = oc_syms[(int)objects[CORPSE].oc_class];
161#ifdef ROGUE_COLOR
162	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color)
163	    color = CLR_RED;
164	else
165#endif
166	    mon_color(offset);
167	    special |= MG_CORPSE;
168    } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) {	/* mon detect */
169	ch = monsyms[(int)mons[offset].mlet];
170#ifdef ROGUE_COLOR
171	if (HAS_ROGUE_IBM_GRAPHICS)
172	    color = NO_COLOR;	/* no need to check iflags.use_color */
173	else
174#endif
175	    mon_color(offset);
176	/* Disabled for now; anyone want to get reverse video to work? */
177	/* is_reverse = TRUE; */
178	    special |= MG_DETECT;
179    } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) {	/* invisible */
180	ch = DEF_INVISIBLE;
181#ifdef ROGUE_COLOR
182	if (HAS_ROGUE_IBM_GRAPHICS)
183	    color = NO_COLOR;	/* no need to check iflags.use_color */
184	else
185#endif
186	    invis_color(offset);
187	    special |= MG_INVIS;
188    } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) {	/* a pet */
189	ch = monsyms[(int)mons[offset].mlet];
190#ifdef ROGUE_COLOR
191	if (HAS_ROGUE_IBM_GRAPHICS)
192	    color = NO_COLOR;	/* no need to check iflags.use_color */
193	else
194#endif
195	    pet_color(offset);
196	    special |= MG_PET;
197    } else {							/* a monster */
198	ch = monsyms[(int)mons[glyph].mlet];
199#ifdef ROGUE_COLOR
200	if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) {
201	    if (x == u.ux && y == u.uy)
202		/* actually player should be yellow-on-gray if in a corridor */
203		color = CLR_YELLOW;
204	    else
205		color = NO_COLOR;
206	} else
207#endif
208	{
209	    mon_color(glyph);
210	    /* special case the hero for `showrace' option */
211#ifdef TEXTCOLOR
212	    if (iflags.use_color && x == u.ux && y == u.uy &&
213		    iflags.showrace && !Upolyd)
214		color = HI_DOMESTIC;
215#endif
216	}
217    }
218
219#ifdef TEXTCOLOR
220    /* Turn off color if no color defined, or rogue level w/o PC graphics. */
221# ifdef REINCARNATION
222#  ifdef ASCIIGRAPH
223    if (!has_color(color) || (Is_rogue_level(&u.uz) && !HAS_ROGUE_IBM_GRAPHICS))
224#  else
225    if (!has_color(color) || Is_rogue_level(&u.uz))
226#  endif
227# else
228    if (!has_color(color))
229# endif
230	color = NO_COLOR;
231#endif
232
233    *ochar = (int)ch;
234    *ospecial = special;
235#ifdef TEXTCOLOR
236    *ocolor = color;
237#endif
238    return;
239}
240
241/*mapglyph.c*/
242