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))
57 #define is_objpile(x,y) (!Hallucination && level.objects[(x)][(y)] \
58 && level.objects[(x)][(y)]->nexthere)
62 mapglyph(glyph
, ochar
, ocolor
, ospecial
, x
, y
)
63 int glyph
, *ocolor
, x
, y
;
67 register int offset
, idx
;
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
;
90 special
|= MG_OBJPILE
;
91 } else if ((offset
= (glyph
- GLYPH_WARNING_OFF
)) >= 0) { /* warn flash */
92 idx
= offset
+ SYM_OFF_W
;
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
)
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
)
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
)
119 else if (offset
>= S_arrow_trap
&& offset
<= S_polymorph_trap
)
121 else if (offset
== S_corr
|| offset
== S_litcorr
)
123 else if (offset
>= S_room
&& offset
<= S_water
124 && offset
!= S_darkroom
)
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
]) {
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
;
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
) {
157 color
= CLR_BRIGHT_BLUE
;
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
;
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 */
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
)
180 special
|= MG_CORPSE
;
182 special
|= MG_OBJPILE
;
183 } else if ((offset
= (glyph
- GLYPH_DETECT_OFF
)) >= 0) { /* mon detect */
184 idx
= mons
[offset
].mlet
+ SYM_OFF_M
;
186 color
= NO_COLOR
; /* no need to check iflags.use_color */
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
;
195 color
= NO_COLOR
; /* no need to check iflags.use_color */
199 } else if ((offset
= (glyph
- GLYPH_PET_OFF
)) >= 0) { /* a pet */
200 idx
= mons
[offset
].mlet
+ SYM_OFF_M
;
202 color
= NO_COLOR
; /* no need to check iflags.use_color */
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 */
217 /* special case the hero for `showrace' option */
218 if (iflags
.use_color
&& x
== u
.ux
&& y
== u
.uy
219 && flags
.showrace
&& !Upolyd
)
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
))
244 static char encbuf
[20];
246 Sprintf(encbuf
, "\\G%04X%04X", context
.rndencode
, glyph
);
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
263 genl_putmixed(window
, attr
, str
)
268 static const char hex
[] = "00112233445566778899aAbBcCdDeEfF";
270 const char *cp
= str
;
275 int rndchk
, dcount
, so
, gv
, ch
= 0, oc
= 0;
277 const char *dp
, *save_cp
;
281 case 'G': /* glyph value \GXXXXNNNN*/
283 for (++cp
; *cp
&& ++dcount
<= 4; ++cp
)
284 if ((dp
= index(hex
, *cp
)) != 0)
285 rndchk
= (rndchk
* 16) + ((int) (dp
- hex
) / 2);
288 if (rndchk
== context
.rndencode
) {
290 for (; *cp
&& ++dcount
<= 4; ++cp
)
291 if ((dp
= index(hex
, *cp
)) != 0)
292 gv
= (gv
* 16) + ((int) (dp
- hex
) / 2);
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 */
301 /* possible forgery - leave it the way it is */
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);
313 if (rndchk
== context
.rndencode
) {
315 for (; *cp
&& ++dcount
<= 2; ++cp
)
316 if ((dp
= index(hex
, *cp
)) != 0)
317 so
= (so
* 16) + ((int) (dp
- hex
) / 2);
321 *put
++ = showsyms
[so
];
331 /* now send it to the normal putstr */
332 putstr(window
, attr
, buf
);