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. */
6 #if defined(TTY_GRAPHICS)
7 #include "wintty.h" /* for prototype of has_color() only */
10 #define HI_DOMESTIC CLR_WHITE /* monst.c */
12 static int explcolors
[] = {
14 CLR_GREEN
, /* noxious */
15 CLR_BROWN
, /* muddy */
17 CLR_MAGENTA
, /* magical */
18 CLR_ORANGE
, /* fiery */
19 CLR_WHITE
, /* frosty */
22 #if !defined(TTY_GRAPHICS)
23 #define has_color(n) TRUE
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 */
43 #define invis_color(n)
46 #define explode_color(n)
49 #if defined(USE_TILES) && defined(MSDOS)
50 #define HAS_ROGUE_IBM_GRAPHICS \
51 (currentgraphics == ROGUESET && SYMHANDLING(H_IBM) && !iflags.grmode)
53 #define HAS_ROGUE_IBM_GRAPHICS \
54 (currentgraphics == ROGUESET && SYMHANDLING(H_IBM))
59 mapglyph(glyph
, ochar
, ocolor
, ospecial
, x
, y
)
60 int glyph
, *ocolor
, x
, y
;
64 register int offset
, idx
;
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
;
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
;
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
)
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
)
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
)
116 else if (offset
>= S_arrow_trap
&& offset
<= S_polymorph_trap
)
118 else if (offset
== S_corr
|| offset
== S_litcorr
)
120 else if (offset
>= S_room
&& offset
<= S_water
121 && offset
!= S_darkroom
)
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
]) {
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
) {
148 color
= CLR_BRIGHT_BLUE
;
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
;
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 */
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
)
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
;
178 color
= NO_COLOR
; /* no need to check iflags.use_color */
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
;
187 color
= NO_COLOR
; /* no need to check iflags.use_color */
191 } else if ((offset
= (glyph
- GLYPH_PET_OFF
)) >= 0) { /* a pet */
192 idx
= mons
[offset
].mlet
+ SYM_OFF_M
;
194 color
= NO_COLOR
; /* no need to check iflags.use_color */
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 */
209 /* special case the hero for `showrace' option */
210 if (iflags
.use_color
&& x
== u
.ux
&& y
== u
.uy
211 && flags
.showrace
&& !Upolyd
)
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
))
236 static char encbuf
[20];
238 Sprintf(encbuf
, "\\G%04X%04X", context
.rndencode
, glyph
);
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
255 genl_putmixed(window
, attr
, str
)
260 static const char hex
[] = "00112233445566778899aAbBcCdDeEfF";
262 const char *cp
= str
;
267 int rndchk
, dcount
, so
, gv
, ch
= 0, oc
= 0;
269 const char *dp
, *save_cp
;
273 case 'G': /* glyph value \GXXXXNNNN*/
275 for (++cp
; *cp
&& ++dcount
<= 4; ++cp
)
276 if ((dp
= index(hex
, *cp
)) != 0)
277 rndchk
= (rndchk
* 16) + ((int) (dp
- hex
) / 2);
280 if (rndchk
== context
.rndencode
) {
282 for (; *cp
&& ++dcount
<= 4; ++cp
)
283 if ((dp
= index(hex
, *cp
)) != 0)
284 gv
= (gv
* 16) + ((int) (dp
- hex
) / 2);
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 */
293 /* possible forgery - leave it the way it is */
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);
305 if (rndchk
== context
.rndencode
) {
307 for (; *cp
&& ++dcount
<= 2; ++cp
)
308 if ((dp
= index(hex
, *cp
)) != 0)
309 so
= (so
* 16) + ((int) (dp
- hex
) / 2);
313 *put
++ = showsyms
[so
];
323 /* now send it to the normal putstr */
324 putstr(window
, attr
, buf
);