NetHack->aNetHack
[aNetHack.git] / src / mapglyph.c
blob4ba4ee7e6fdebdc4107b7c30af4d4f9e6bb86a00
1 /* NetHack 3.6 mapglyph.c $NHDT-Date: 1448175698 2015/11/22 07:01:38 $ $NHDT-Branch: master $:$NHDT-Revision: 1.40 $ */
2 /* Copyright (c) David Cohrs, 1991 */
3 /* NetHack may be freely redistributed. See license for details. */
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 */
12 static int 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 */
22 #if !defined(TTY_GRAPHICS)
23 #define has_color(n) TRUE
24 #endif
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) \
34 color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR
35 #define explode_color(n) color = iflags.use_color ? explcolors[n] : NO_COLOR
37 #else /* no text color */
39 #define zap_color(n)
40 #define cmap_color(n)
41 #define obj_color(n)
42 #define mon_color(n)
43 #define invis_color(n)
44 #define pet_color(c)
45 #define warn_color(n)
46 #define explode_color(n)
47 #endif
49 #if defined(USE_TILES) && defined(MSDOS)
50 #define HAS_ROGUE_IBM_GRAPHICS \
51 (currentgraphics == ROGUESET && SYMHANDLING(H_IBM) && !iflags.grmode)
52 #else
53 #define HAS_ROGUE_IBM_GRAPHICS \
54 (currentgraphics == ROGUESET && SYMHANDLING(H_IBM))
55 #endif
57 #define is_objpile(x,y) (!Hallucination && level.objects[(x)][(y)] \
58 && level.objects[(x)][(y)]->nexthere)
60 /*ARGSUSED*/
61 int
62 mapglyph(glyph, ochar, ocolor, ospecial, x, y)
63 int glyph, *ocolor, x, y;
64 int *ochar;
65 unsigned *ospecial;
67 register int offset, idx;
68 int color = NO_COLOR;
69 nhsym ch;
70 unsigned special = 0;
71 /* condense multiple tests in macro version down to single */
72 boolean has_rogue_ibm_graphics = HAS_ROGUE_IBM_GRAPHICS;
73 boolean has_rogue_color = (has_rogue_ibm_graphics
74 && symset[currentgraphics].nocolor == 0);
77 * Map the glyph back to a character and color.
79 * Warning: For speed, this makes an assumption on the order of
80 * offsets. The order is set in display.h.
82 if ((offset = (glyph - GLYPH_STATUE_OFF)) >= 0) { /* a statue */
83 idx = mons[offset].mlet + SYM_OFF_M;
84 if (has_rogue_color)
85 color = CLR_RED;
86 else
87 obj_color(STATUE);
88 special |= MG_STATUE;
89 if (is_objpile(x,y))
90 special |= MG_OBJPILE;
91 } else if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* warn flash */
92 idx = offset + SYM_OFF_W;
93 if (has_rogue_color)
94 color = NO_COLOR;
95 else
96 warn_color(offset);
97 } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */
98 /* see swallow_to_glyph() in display.c */
99 idx = (S_sw_tl + (offset & 0x7)) + SYM_OFF_P;
100 if (has_rogue_color && iflags.use_color)
101 color = NO_COLOR;
102 else
103 mon_color(offset >> 3);
104 } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */
105 /* see zapdir_to_glyph() in display.c */
106 idx = (S_vbeam + (offset & 0x3)) + SYM_OFF_P;
107 if (has_rogue_color && iflags.use_color)
108 color = NO_COLOR;
109 else
110 zap_color((offset >> 2));
111 } else if ((offset = (glyph - GLYPH_EXPLODE_OFF)) >= 0) { /* explosion */
112 idx = ((offset % MAXEXPCHARS) + S_explode1) + SYM_OFF_P;
113 explode_color(offset / MAXEXPCHARS);
114 } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */
115 idx = offset + SYM_OFF_P;
116 if (has_rogue_color && iflags.use_color) {
117 if (offset >= S_vwall && offset <= S_hcdoor)
118 color = CLR_BROWN;
119 else if (offset >= S_arrow_trap && offset <= S_polymorph_trap)
120 color = CLR_MAGENTA;
121 else if (offset == S_corr || offset == S_litcorr)
122 color = CLR_GRAY;
123 else if (offset >= S_room && offset <= S_water
124 && offset != S_darkroom)
125 color = CLR_GREEN;
126 else
127 color = NO_COLOR;
128 #ifdef TEXTCOLOR
129 /* provide a visible difference if normal and lit corridor
130 use the same symbol */
131 } else if (iflags.use_color && offset == S_litcorr
132 && showsyms[idx] == showsyms[S_corr + SYM_OFF_P]) {
133 color = CLR_WHITE;
134 #endif
135 /* try to provide a visible difference between water and lava
136 if they use the same symbol and color is disabled */
137 } else if (!iflags.use_color && offset == S_lava
138 && (showsyms[idx] == showsyms[S_pool + SYM_OFF_P]
139 || showsyms[idx] == showsyms[S_water + SYM_OFF_P])) {
140 special |= MG_BW_LAVA;
141 } else {
142 cmap_color(offset);
144 } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */
145 idx = objects[offset].oc_class + SYM_OFF_O;
146 if (offset == BOULDER)
147 idx = SYM_BOULDER + SYM_OFF_X;
148 if (has_rogue_color && iflags.use_color) {
149 switch (objects[offset].oc_class) {
150 case COIN_CLASS:
151 color = CLR_YELLOW;
152 break;
153 case FOOD_CLASS:
154 color = CLR_RED;
155 break;
156 default:
157 color = CLR_BRIGHT_BLUE;
158 break;
160 } else
161 obj_color(offset);
162 if (offset != BOULDER && is_objpile(x,y))
163 special |= MG_OBJPILE;
164 } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */
165 idx = mons[offset].mlet + SYM_OFF_M;
166 if (has_rogue_color)
167 /* This currently implies that the hero is here -- monsters */
168 /* don't ride (yet...). Should we set it to yellow like in */
169 /* the monster case below? There is no equivalent in rogue. */
170 color = NO_COLOR; /* no need to check iflags.use_color */
171 else
172 mon_color(offset);
173 special |= MG_RIDDEN;
174 } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */
175 idx = objects[CORPSE].oc_class + SYM_OFF_O;
176 if (has_rogue_color && iflags.use_color)
177 color = CLR_RED;
178 else
179 mon_color(offset);
180 special |= MG_CORPSE;
181 if (is_objpile(x,y))
182 special |= MG_OBJPILE;
183 } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */
184 idx = mons[offset].mlet + SYM_OFF_M;
185 if (has_rogue_color)
186 color = NO_COLOR; /* no need to check iflags.use_color */
187 else
188 mon_color(offset);
189 /* Disabled for now; anyone want to get reverse video to work? */
190 /* is_reverse = TRUE; */
191 special |= MG_DETECT;
192 } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */
193 idx = SYM_INVISIBLE + SYM_OFF_X;
194 if (has_rogue_color)
195 color = NO_COLOR; /* no need to check iflags.use_color */
196 else
197 invis_color(offset);
198 special |= MG_INVIS;
199 } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */
200 idx = mons[offset].mlet + SYM_OFF_M;
201 if (has_rogue_color)
202 color = NO_COLOR; /* no need to check iflags.use_color */
203 else
204 pet_color(offset);
205 special |= MG_PET;
206 } else { /* a monster */
207 idx = mons[glyph].mlet + SYM_OFF_M;
208 if (has_rogue_color && iflags.use_color) {
209 if (x == u.ux && y == u.uy)
210 /* actually player should be yellow-on-gray if in corridor */
211 color = CLR_YELLOW;
212 else
213 color = NO_COLOR;
214 } else {
215 mon_color(glyph);
216 #ifdef TEXTCOLOR
217 /* special case the hero for `showrace' option */
218 if (iflags.use_color && x == u.ux && y == u.uy
219 && flags.showrace && !Upolyd)
220 color = HI_DOMESTIC;
221 #endif
225 ch = showsyms[idx];
226 #ifdef TEXTCOLOR
227 /* Turn off color if no color defined, or rogue level w/o PC graphics. */
228 if (!has_color(color) || (Is_rogue_level(&u.uz) && !has_rogue_color))
229 color = NO_COLOR;
230 #endif
232 *ochar = (int) ch;
233 *ospecial = special;
234 #ifdef TEXTCOLOR
235 *ocolor = color;
236 #endif
237 return idx;
240 char *
241 encglyph(glyph)
242 int glyph;
244 static char encbuf[20];
246 Sprintf(encbuf, "\\G%04X%04X", context.rndencode, glyph);
247 return encbuf;
251 * This differs from putstr() because the str parameter can
252 * contain a sequence of characters representing:
253 * \GXXXXNNNN a glyph value, encoded by encglyph().
255 * For window ports that haven't yet written their own
256 * XXX_putmixed() routine, this general one can be used.
257 * It replaces the encoded glyph sequence with a single
258 * showsyms[] char, then just passes that string onto
259 * putstr().
262 void
263 genl_putmixed(window, attr, str)
264 winid window;
265 int attr;
266 const char *str;
268 static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
269 char buf[BUFSZ];
270 const char *cp = str;
271 char *put = buf;
273 while (*cp) {
274 if (*cp == '\\') {
275 int rndchk, dcount, so, gv, ch = 0, oc = 0;
276 unsigned os = 0;
277 const char *dp, *save_cp;
279 save_cp = cp++;
280 switch (*cp) {
281 case 'G': /* glyph value \GXXXXNNNN*/
282 rndchk = dcount = 0;
283 for (++cp; *cp && ++dcount <= 4; ++cp)
284 if ((dp = index(hex, *cp)) != 0)
285 rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
286 else
287 break;
288 if (rndchk == context.rndencode) {
289 gv = dcount = 0;
290 for (; *cp && ++dcount <= 4; ++cp)
291 if ((dp = index(hex, *cp)) != 0)
292 gv = (gv * 16) + ((int) (dp - hex) / 2);
293 else
294 break;
295 so = mapglyph(gv, &ch, &oc, &os, 0, 0);
296 *put++ = showsyms[so];
297 /* 'cp' is ready for the next loop iteration and '*cp'
298 should not be copied at the end of this iteration */
299 continue;
300 } else {
301 /* possible forgery - leave it the way it is */
302 cp = save_cp;
304 break;
305 #if 0
306 case 'S': /* symbol offset */
307 so = rndchk = dcount = 0;
308 for (++cp; *cp && ++dcount <= 4; ++cp)
309 if ((dp = index(hex, *cp)) != 0)
310 rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
311 else
312 break;
313 if (rndchk == context.rndencode) {
314 dcount = 0;
315 for (; *cp && ++dcount <= 2; ++cp)
316 if ((dp = index(hex, *cp)) != 0)
317 so = (so * 16) + ((int) (dp - hex) / 2);
318 else
319 break;
321 *put++ = showsyms[so];
322 break;
323 #endif
324 case '\\':
325 break;
328 *put++ = *cp++;
330 *put = '\0';
331 /* now send it to the normal putstr */
332 putstr(window, attr, buf);
335 /*mapglyph.c*/