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