1 /* $Id: guimap.c,v 5.7 2002/02/10 19:29:39 bertg Exp $
2  *
3  * XPilot, a multiplayer gravity war game.  Copyright (C) 1991-2001 by
4  *
5  *      Bj�rn Stabell        <bjoern@xpilot.org>
6  *      Ken Ronny Schouten   <ken@xpilot.org>
7  *      Bert Gijsbers        <bert@xpilot.org>
8  *      Dick Balaska         <dick@xpilot.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 
31 #ifndef _WINDOWS
32 # include <unistd.h>
33 # include <X11/Xlib.h>
34 # include <X11/Xos.h>
35 #endif
36 
37 #ifdef _WINDOWS
38 # include "NT/winX.h"
39 # include "NT/winBitmap.h"
40 #endif
41 
42 #include "gfx2d.h"
43 #include "version.h"
44 #include "config.h"
45 #include "const.h"
46 #include "error.h"
47 #include "bit.h"
48 #include "types.h"
49 #include "keys.h"
50 #include "rules.h"
51 #include "setup.h"
52 #include "texture.h"
53 #include "paint.h"
54 #include "paintdata.h"
55 #include "paintmacros.h"
56 #include "record.h"
57 #include "xinit.h"
58 #include "protoclient.h"
59 #include "blockbitmaps.h"
60 #include "guimap.h"
61 
62 
63 char guimap_version[] = VERSION;
64 
65 
66 /* XXX better include a header. */
67 extern int	wallColor;		/* Color index for wall drawing */
68 extern int	decorColor;		/* Color index for decoration drawing */
69 extern char	*wallTextureFile;	/* Filename of wall texture */
70 extern char	*decorTextureFile;	/* Filename of decor texture */
71 
72 
73 extern setup_t	*Setup;
74 
75 
Gui_paint_walls(int x,int y,int type,int xi,int yi)76 void Gui_paint_walls(int x, int y, int type, int xi, int yi)
77 {
78     if (!blockBitmaps) {
79 	if (type & BLUE_LEFT) {
80 	    Segment_add(wallColor,
81 			X(x),
82 			Y(y),
83 			X(x),
84 			Y(y+BLOCK_SZ));
85 	}
86 	if (type & BLUE_DOWN) {
87 	    Segment_add(wallColor,
88 			X(x),
89 			Y(y),
90 			X(x+BLOCK_SZ),
91 			Y(y));
92 	}
93 	if (type & BLUE_RIGHT) {
94 	    Segment_add(wallColor,
95 			X(x+BLOCK_SZ),
96 			Y(y),
97 			X(x+BLOCK_SZ),
98 			Y(y+BLOCK_SZ));
99 	}
100 	if (type & BLUE_UP) {
101 	    Segment_add(wallColor,
102 			X(x),
103 			Y(y+BLOCK_SZ),
104 			X(x+BLOCK_SZ),
105 			Y(y+BLOCK_SZ));
106 	}
107 
108 	if ((type & BLUE_FUEL) == BLUE_FUEL) {
109 	}
110 	else if (type & BLUE_OPEN) {
111 	    Segment_add(wallColor,
112 			X(x),
113 			Y(y),
114 			X(x+BLOCK_SZ),
115 			Y(y+BLOCK_SZ));
116 	}
117 	else if (type & BLUE_CLOSED) {
118 	    Segment_add(wallColor,
119 			X(x),
120 			Y(y+BLOCK_SZ),
121 			X(x+BLOCK_SZ),
122 			Y(y));
123 	}
124     }
125     else {
126 
127 	if (type & BLUE_LEFT) {
128 	    PaintBitmap(p_draw, BM_WALL_LEFT, WINSCALE(X(x - 1)),
129 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
130 			WINSCALE(BLOCK_SZ), 0);
131 	}
132 	if (type & BLUE_DOWN) {
133 	    PaintBitmap(p_draw, BM_WALL_BOTTOM, WINSCALE(X(x)),
134 			WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
135 			WINSCALE(BLOCK_SZ), 0);
136 	}
137 	if (type & BLUE_RIGHT) {
138 	    PaintBitmap(p_draw, BM_WALL_RIGHT, WINSCALE(X(x + 1)),
139 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
140 			WINSCALE(BLOCK_SZ), 0);
141 	}
142 	if (type & BLUE_UP) {
143 	    PaintBitmap(p_draw, BM_WALL_TOP, WINSCALE(X(x)),
144 			WINSCALE(Y(y + BLOCK_SZ + 1)), WINSCALE(BLOCK_SZ),
145 			WINSCALE(BLOCK_SZ), 0);
146 	}
147 	if ((type & BLUE_FUEL) == BLUE_FUEL) {
148 	}
149 
150 	else if (type & BLUE_OPEN) {
151 	    PaintBitmap(p_draw, BM_WALL_UR, WINSCALE(X(x)),
152 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
153 			WINSCALE(BLOCK_SZ), 0);
154 	}
155 	else if (type & BLUE_CLOSED) {
156 	    PaintBitmap(p_draw, BM_WALL_UL, WINSCALE(X(x)),
157 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
158 			WINSCALE(BLOCK_SZ), 0);
159 	}
160     }
161 }
162 
163 
Gui_paint_cannon(int x,int y,int type)164 void Gui_paint_cannon(int x, int y, int type)
165 {
166     if (!blockBitmaps) {
167 	XPoint		points[5];
168 
169 	SET_FG(colors[WHITE].pixel);
170 	switch (type) {
171 	case SETUP_CANNON_UP:
172 	    points[0].x = WINSCALE(X(x));
173 	    points[0].y = WINSCALE(Y(y));
174 	    points[1].x = WINSCALE(X(x+BLOCK_SZ));
175 	    points[1].y = WINSCALE(Y(y));
176 	    points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
177 	    points[2].y = WINSCALE(Y(y+BLOCK_SZ/3));
178 	    break;
179 	case SETUP_CANNON_DOWN:
180 	    points[0].x = WINSCALE(X(x));
181 	    points[0].y = WINSCALE(Y(y+BLOCK_SZ));
182 	    points[1].x = WINSCALE(X(x+BLOCK_SZ));
183 	    points[1].y = WINSCALE(Y(y+BLOCK_SZ));
184 	    points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
185 	    points[2].y = WINSCALE(Y(y+2*BLOCK_SZ/3));
186 	    break;
187 	case SETUP_CANNON_RIGHT:
188 	    points[0].x = WINSCALE(X(x));
189 	    points[0].y = WINSCALE(Y(y));
190 	    points[1].x = WINSCALE(X(x));
191 	    points[1].y = WINSCALE(Y(y+BLOCK_SZ));
192 	    points[2].x = WINSCALE(X(x+BLOCK_SZ/3));
193 	    points[2].y = WINSCALE(Y(y+BLOCK_SZ/2));
194 	    break;
195 	case SETUP_CANNON_LEFT:
196 	    points[0].x = WINSCALE(X(x+BLOCK_SZ));
197 	    points[0].y = WINSCALE(Y(y));
198 	    points[1].x = WINSCALE(X(x+BLOCK_SZ));
199 	    points[1].y = WINSCALE(Y(y+BLOCK_SZ));
200 	    points[2].x = WINSCALE(X(x+2*BLOCK_SZ/3));
201 	    points[2].y = WINSCALE(Y(y+BLOCK_SZ/2));
202 	    break;
203 	default:
204 	    errno = 0;
205 	    error("Unknown cannon type %d", type);
206 	    return;
207 	}
208 	points[3] = points[0];
209 	rd.drawLines(dpy, p_draw, gc, points, 4, 0);
210 	Erase_points(0, points, 4);
211     }
212     else {
213 	switch (type) {
214 	case SETUP_CANNON_UP:
215 	    PaintBitmap(p_draw, BM_CANNON_DOWN, WINSCALE(X(x)),
216 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
217 			WINSCALE(BLOCK_SZ), 0);
218 	    break;
219 	case SETUP_CANNON_DOWN:
220 	    PaintBitmap(p_draw, BM_CANNON_UP, WINSCALE(X(x)),
221 			WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
222 			WINSCALE(BLOCK_SZ), 0);
223 	    break;
224 	case SETUP_CANNON_LEFT:
225 	    PaintBitmap(p_draw, BM_CANNON_RIGHT, WINSCALE(X(x)),
226 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
227 			WINSCALE(BLOCK_SZ), 0);
228 	    break;
229 	case SETUP_CANNON_RIGHT:
230 	    PaintBitmap(p_draw, BM_CANNON_LEFT, WINSCALE(X(x - 1)),
231 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
232 			WINSCALE(BLOCK_SZ), 0);
233 	    break;
234 	default:
235 	    errno = 0;
236 	    error("Bad base dir.");
237 	    return;
238 	}
239     }
240 }
241 
242 
Gui_paint_fuel(int x,int y,int fuel)243 void Gui_paint_fuel(int x, int y, int fuel)
244 {
245 	int fuel_images = Block_bitmap_images(BM_FUEL);
246 
247     if (!blockBitmaps || !fuel_images) {
248 #define FUEL_BORDER 2
249 	int			size;
250 
251 	static char		s[2] = "F";
252 	static int		text_width = 0;
253 	static int		text_is_bigger;
254 
255 #ifndef WINDOWSCALING
256 	if (!text_width)
257 #else
258 	static DFLOAT		lastScaleFactor;
259 
260 	if (!text_width || lastScaleFactor != scaleFactor)
261 #endif
262 	{
263 #ifdef WINDOWSCALING
264 
265 	    lastScaleFactor = scaleFactor;
266 #endif
267 	    text_width = XTextWidth(gameFont, s, 1);
268 	    text_is_bigger = text_width+4 > WINSCALE(BLOCK_SZ)+1 ||
269 			    (gameFont->ascent + gameFont->descent) > WINSCALE(BLOCK_SZ) + 2;
270 	}
271 	SET_FG(colors[RED].pixel);
272 	size = (BLOCK_SZ - 2*FUEL_BORDER) * fuel / MAX_STATION_FUEL;
273 	if (useErase) {
274 	/* speedup for slow old cheap graphics cards like cg3.
275 	    or Xterminals with slow connection */
276 	    rd.drawLine(dpy, p_draw, gc,
277 			WINSCALE(X(x + FUEL_BORDER)),
278 			WINSCALE(Y(y + FUEL_BORDER + size)),
279 			WINSCALE(X(x + FUEL_BORDER + (BLOCK_SZ - 2*FUEL_BORDER))),
280 			WINSCALE(Y(y + FUEL_BORDER + size)));
281 	} else {
282 	    rd.fillRectangle(dpy, p_draw, gc,
283 			     WINSCALE(X(x + FUEL_BORDER)),
284 			     WINSCALE(Y(y + FUEL_BORDER + size)),
285 			     WINSCALE(BLOCK_SZ - 2*FUEL_BORDER + 1),
286 			     WINSCALE(size + 1));
287 	}
288 	if (!text_is_bigger)
289 	    Erase_rectangle(WINSCALE(X(x)) - 1,
290 			    WINSCALE(Y(y + BLOCK_SZ)) - 1,
291 			    WINSCALE(BLOCK_SZ) + 2,
292 			    WINSCALE(BLOCK_SZ) + 2);
293 
294 	/* Draw F in fuel cells */
295 	XSetFunction(dpy, gc, GXxor);
296 	SET_FG(colors[BLACK].pixel ^ colors[RED].pixel);
297 	x = WINSCALE(X(x + BLOCK_SZ/2)) - text_width/2,
298 	y = WINSCALE(Y(y + BLOCK_SZ/2)) + gameFont->ascent/2,
299 	rd.drawString(dpy, p_draw, gc, x, y, s, 1);
300 	XSetFunction(dpy, gc, GXcopy);
301 
302 	if (text_is_bigger)
303 	    Erase_rectangle(x - 2, y - gameFont->ascent,
304 			    text_width + 4, gameFont->ascent + gameFont->descent);
305     }
306     else {
307 #define BITMAP_FUEL_BORDER 3
308 
309 	int size;
310 	/* x + x * y will give a pseudo random number,
311 	so different fuelcells will not be displayed with the same image-frame.*/
312 	int image = ( (loops + x + x * y) % (fuel_images * 2) );
313 
314 	/* the animation is played from image 0-15 then back again from image 15-0 */
315 
316 	if (image >= fuel_images)
317 	    image = (2 * fuel_images - 1) - image;
318 
319 
320 	size = (BLOCK_SZ - 2 * BITMAP_FUEL_BORDER) * fuel / MAX_STATION_FUEL;
321 
322 	PaintBitmap(p_draw, BM_FUELCELL, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
323 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
324 
325 	PaintFuelSlice(p_draw, BM_FUEL,
326 		      WINSCALE(X(x + BITMAP_FUEL_BORDER)),
327 		       WINSCALE(Y(y + size + BITMAP_FUEL_BORDER)),
328 		       WINSCALE(BLOCK_SZ - 2 * BITMAP_FUEL_BORDER),
329 		       WINSCALE(BLOCK_SZ - 2 * BITMAP_FUEL_BORDER),
330 		       image, WINSCALE(size));
331 
332 	Erase_rectangle(WINSCALE(X(x)) - 1,
333 			WINSCALE(Y(y + BLOCK_SZ)) - 1,
334 			WINSCALE(BLOCK_SZ) + 2, WINSCALE(BLOCK_SZ) + 2);
335 
336     }
337 }
338 
339 
Gui_paint_base(int x,int y,int xi,int yi,int type)340 void Gui_paint_base(int x, int y, int xi, int yi, int type)
341 {
342     if (!blockBitmaps) {
343 	const int	BORDER = 4;					/* in pixels */
344 	int		id, team, size;
345 	other_t	*other;
346 	char	s[3];
347 
348 	SET_FG(colors[WHITE].pixel);
349 
350 	switch (type) {
351 	case SETUP_BASE_UP:
352 	    Segment_add(WHITE,
353 			X(x), Y(y-1),
354 			X(x+BLOCK_SZ), Y(y-1));
355 	    break;
356 	case SETUP_BASE_DOWN:
357 	    Segment_add(WHITE,
358 			X(x), Y(y+BLOCK_SZ+1),
359 			X(x+BLOCK_SZ), Y(y+BLOCK_SZ+1));
360 	    break;
361 	case SETUP_BASE_LEFT:
362 	    Segment_add(WHITE,
363 			X(x+BLOCK_SZ+1), Y(y+BLOCK_SZ),
364 			X(x+BLOCK_SZ+1), Y(y));
365 	    break;
366 	case SETUP_BASE_RIGHT:
367 	    Segment_add(WHITE,
368 			X(x-1), Y(y+BLOCK_SZ),
369 			X(x-1), Y(y));
370 	    break;
371 	default:
372 	    errno = 0;
373 	    error("Bad base dir.");
374 	    return;
375 	}
376 	/* only draw base teams if ship naming is on, SKS 25/05/94 */
377 	if (!BIT(instruments, SHOW_SHIP_NAME) ||
378 	    Base_info_by_pos(xi, yi, &id, &team) == -1)
379 	    return;
380 
381 	/* operate in pixels from here out */
382 	x = WINSCALE(X(x));
383 	y = WINSCALE(Y(y));
384 
385 	if ((other = Other_by_id(id)) != NULL) {
386 	    if (other->name_width == 0) {
387 		other->name_len = strlen(other->name);
388 		other->name_width = 2 + XTextWidth(gameFont, other->name,
389 						   other->name_len);
390 	    }
391 	}
392 	if (BIT(Setup->mode, TEAM_PLAY)) {
393 	    s[0] = '0' + team;
394 	    if (other) {
395 		s[1] = ' ';
396 		s[2] = '\0';
397 	    } else
398 		s[1] = '\0';
399 		size = XTextWidth(gameFont, s, other ? 2 : 1);
400 	} else
401 	    size = 0;
402 
403 	switch (type) {
404 	case SETUP_BASE_UP:
405 	    y += BORDER + gameFont->ascent;
406 	    x += WINSCALE(BLOCK_SZ/2);
407 	    x -= size / 2 + (other ? other->name_width/2 : 0);
408 	    break;
409 	case SETUP_BASE_DOWN:
410 	    y -= WINSCALE(BLOCK_SZ) + BORDER + gameFont->descent;
411 	    x += WINSCALE(BLOCK_SZ/2);
412 	    x -= size / 2 + (other ? other->name_width/2 : 0);
413 	    break;
414 	case SETUP_BASE_LEFT:
415 	    x += WINSCALE(BLOCK_SZ) + BORDER;
416 	    y += -WINSCALE(BLOCK_SZ/2) + gameFont->ascent/2;
417 	    break;
418 	case SETUP_BASE_RIGHT:
419 	    x -= BORDER + (other ? other->name_width : 0) + size;
420 	    y += -WINSCALE(BLOCK_SZ/2) + gameFont->ascent/2;
421 	    break;
422 	}
423 	if (size) {
424 	    rd.drawString(dpy, p_draw, gc, x, y, s, other ? 2 : 1);
425 	     Erase_rectangle(x - 1, y - gameFont->ascent - 1,
426 			     size + 2,
427 			     gameFont->ascent + gameFont->descent+2);
428 	     x += size;
429 	}
430 	if (other) {
431 	     rd.drawString(dpy, p_draw, gc, x, y,
432 			   other->name, other->name_len);
433 	     Erase_rectangle(x - 1,
434 			     y - gameFont->ascent - 1,
435 			     other->name_width + 2,
436 			     gameFont->ascent+gameFont->descent + 2);
437 	}
438     }
439     else {
440 	const int BORDER = 4;	/* in pixels */
441 	int id, team, size;
442 	other_t *other;
443 	char s[3];
444 
445 	SET_FG(colors[WHITE].pixel);
446 
447 	switch (type) {
448 	case SETUP_BASE_UP:
449 	    PaintBitmap(p_draw, BM_BASE_DOWN, WINSCALE(X(x)),
450 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
451 			WINSCALE(BLOCK_SZ), 0);
452 	    break;
453 	case SETUP_BASE_DOWN:
454 	    PaintBitmap(p_draw, BM_BASE_UP, WINSCALE(X(x)),
455 			WINSCALE(Y(y + BLOCK_SZ - 1)), WINSCALE(BLOCK_SZ),
456 			WINSCALE(BLOCK_SZ), 0);
457 	    break;
458 	case SETUP_BASE_LEFT:
459 	    PaintBitmap(p_draw, BM_BASE_RIGHT, WINSCALE(X(x)),
460 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
461 			WINSCALE(BLOCK_SZ), 0);
462 	    break;
463 	case SETUP_BASE_RIGHT:
464 	    PaintBitmap(p_draw, BM_BASE_LEFT, WINSCALE(X(x - 1)),
465 			WINSCALE(Y(y + BLOCK_SZ)), WINSCALE(BLOCK_SZ),
466 			WINSCALE(BLOCK_SZ), 0);
467 	    break;
468 	default:
469 	    errno = 0;
470 	    error("Bad base dir.");
471 	    return;
472 	}
473 	/* only draw base teams if ship naming is on, SKS 25/05/94 */
474 	if (!BIT(instruments, SHOW_SHIP_NAME) ||
475 	    Base_info_by_pos(xi, yi, &id, &team) == -1)
476 	    return;
477 
478 	/* operate in pixels from here out */
479 	x = WINSCALE(X(x));
480 	y = WINSCALE(Y(y));
481 
482 	if ((other = Other_by_id(id)) != NULL) {
483 	    if (other->name_width == 0) {
484 		other->name_len = strlen(other->name);
485 		other->name_width = 2 + XTextWidth(gameFont, other->name,
486 						   other->name_len);
487 	    }
488 	}
489 	if (BIT(Setup->mode, TEAM_PLAY)) {
490 	    s[0] = '0' + team;
491 	    if (other) {
492 		s[1] = ' ';
493 		s[2] = '\0';
494 	    }
495 	    else
496 		s[1] = '\0';
497 	    size = XTextWidth(gameFont, s, other ? 2 : 1);
498 	}
499 	else
500 	    size = 0;
501 
502 	switch (type) {
503 	case SETUP_BASE_UP:
504 	    y += BORDER + gameFont->ascent;
505 	    x += WINSCALE(BLOCK_SZ / 2);
506 	    x -= size / 2 + (other ? other->name_width / 2 : 0);
507 	    break;
508 	case SETUP_BASE_DOWN:
509 	    y -= WINSCALE(BLOCK_SZ) + BORDER + gameFont->descent;
510 	    x += WINSCALE(BLOCK_SZ / 2);
511 	    x -= size / 2 + (other ? other->name_width / 2 : 0);
512 	    break;
513 	case SETUP_BASE_LEFT:
514 	    x += WINSCALE(BLOCK_SZ) + BORDER;
515 	    y += -WINSCALE(BLOCK_SZ / 2) + gameFont->ascent / 2;
516 	    break;
517 	case SETUP_BASE_RIGHT:
518 	    x -= BORDER + (other ? other->name_width : 0) + size;
519 	    y += -WINSCALE(BLOCK_SZ / 2) + gameFont->ascent / 2;
520 	    break;
521 	}
522 	if (size) {
523 	    rd.drawString(dpy, p_draw, gc, x, y, s, other ? 2 : 1);
524 	    Erase_rectangle(x - 1, y - gameFont->ascent - 1,
525 			    size + 2, gameFont->ascent + gameFont->descent + 2);
526 	    x += size;
527 	}
528 	if (other) {
529 	    rd.drawString(dpy, p_draw, gc, x, y, other->name, other->name_len);
530 	    Erase_rectangle(x - 1,
531 			    y - gameFont->ascent - 1,
532 			    other->name_width + 2,
533 			    gameFont->ascent + gameFont->descent + 2);
534 	}
535     }
536 }
537 
538 
Gui_paint_decor(int x,int y,int xi,int yi,int type,bool last,bool more_y)539 void Gui_paint_decor(int x, int y, int xi, int yi, int type, bool last, bool more_y)
540 {
541     XPoint		    points[5];
542 
543     int mask;
544     int			    fill_top_left = -1,
545 			    fill_top_right = -1,
546 			    fill_bottom_left = -1,
547 			    fill_bottom_right = -1;
548     static int		    decorTileReady = 0;
549     static Pixmap	    decorTile = None;
550     int			    decorTileDoit = false;
551     static unsigned char    decor[256];
552     static int		    decorReady = 0;
553 
554     SET_FG(colors[decorColor].pixel);
555 
556     if (!decorReady) {
557 	memset(decor, 0, sizeof decor);
558 	decor[SETUP_DECOR_FILLED] = DECOR_UP | DECOR_LEFT | DECOR_DOWN | DECOR_RIGHT;
559 	decor[SETUP_DECOR_RU] = DECOR_UP | DECOR_RIGHT | DECOR_CLOSED;
560 	decor[SETUP_DECOR_RD] = DECOR_DOWN | DECOR_RIGHT | DECOR_OPEN | DECOR_BELOW;
561 	decor[SETUP_DECOR_LU] = DECOR_UP | DECOR_LEFT | DECOR_OPEN;
562 	decor[SETUP_DECOR_LD] = DECOR_LEFT | DECOR_DOWN | DECOR_CLOSED | DECOR_BELOW;
563     }
564 
565     if (BIT(instruments, SHOW_TEXTURED_DECOR)) {
566 	if (!decorTileReady) {
567 	    decorTile = Texture_decor();
568 	    decorTileReady = (decorTile == None) ? -1 : 1;
569 	}
570 	if (decorTileReady == 1) {
571 	    decorTileDoit = true;
572 	    XSetTile(dpy, gc, decorTile);
573 	    XSetTSOrigin(dpy, gc, -WINSCALE(realWorld.x), WINSCALE(realWorld.y));
574 	    XSetFillStyle(dpy, gc, FillTiled);
575 	}
576     }
577 
578     mask = decor[type];
579 
580     if (!BIT(instruments, SHOW_FILLED_DECOR|SHOW_TEXTURED_DECOR)) {
581 	if (mask & DECOR_LEFT) {
582 	    if ((xi == 0)
583 		? (!BIT(Setup->mode, WRAP_PLAY) ||
584 		    !(decor[Setup->map_data[(Setup->x - 1) * Setup->y + yi]]
585 			& DECOR_RIGHT))
586 		: !(decor[Setup->map_data[(xi - 1) * Setup->y + yi]]
587 		    & DECOR_RIGHT)) {
588 		Segment_add(decorColor,
589 			    X(x),
590 			    Y(y),
591 			    X(x),
592 			    Y(y+BLOCK_SZ));
593 	    }
594 	}
595 	if (mask & DECOR_DOWN) {
596 	    if ((yi == 0)
597 		? (!BIT(Setup->mode, WRAP_PLAY) ||
598 		    !(decor[Setup->map_data[xi * Setup->y + Setup->y - 1]]
599 			& DECOR_UP))
600 		: !(decor[Setup->map_data[xi * Setup->y + (yi - 1)]]
601 		    & DECOR_UP)) {
602 		Segment_add(decorColor,
603 			    X(x),
604 			    Y(y),
605 			    X(x+BLOCK_SZ),
606 			    Y(y));
607 	    }
608 	}
609 	if (mask & DECOR_RIGHT) {
610 	    if (!BIT(instruments, SHOW_OUTLINE_DECOR)
611 		|| ((xi == Setup->x - 1)
612 		    ? (!BIT(Setup->mode, WRAP_PLAY)
613 		       || !(decor[Setup->map_data[yi]]
614 			    & DECOR_LEFT))
615 		    : !(decor[Setup->map_data[(xi + 1) * Setup->y + yi]]
616 			& DECOR_LEFT))) {
617 		Segment_add(decorColor,
618 			    X(x+BLOCK_SZ),
619 			    Y(y),
620 			    X(x+BLOCK_SZ),
621 			    Y(y+BLOCK_SZ));
622 	    }
623 	}
624 	if (mask & DECOR_UP) {
625 	    if (!BIT(instruments, SHOW_OUTLINE_DECOR)
626 		|| ((yi == Setup->y - 1)
627 		    ? (!BIT(Setup->mode, WRAP_PLAY)
628 		       || !(decor[Setup->map_data[xi * Setup->y]]
629 			    & DECOR_DOWN))
630 		    : !(decor[Setup->map_data[xi * Setup->y + (yi + 1)]]
631 			& DECOR_DOWN))) {
632 		Segment_add(decorColor,
633 			    X(x),
634 			    Y(y+BLOCK_SZ),
635 			    X(x+BLOCK_SZ),
636 			    Y(y+BLOCK_SZ));
637 	    }
638 	}
639 	if (mask & DECOR_OPEN) {
640 	    Segment_add(decorColor,
641 			X(x),
642 			Y(y),
643 			X(x+BLOCK_SZ),
644 			Y(y+BLOCK_SZ));
645 	}
646 	else if (mask & DECOR_CLOSED) {
647 	    Segment_add(decorColor,
648 			X(x),
649 			Y(y+BLOCK_SZ),
650 			X(x+BLOCK_SZ),
651 			Y(y));
652 	}
653     }
654     else {
655 	if (mask & DECOR_OPEN) {
656 	    if (mask & DECOR_BELOW) {
657 		fill_top_left = x + BLOCK_SZ;
658 		fill_bottom_left = x;
659 		fill_top_right = fill_bottom_right = -1;
660 	    } else {
661 		fill_top_right = x + BLOCK_SZ;
662 		fill_bottom_right = x;
663 	    }
664 	}
665 	else if (mask & DECOR_CLOSED) {
666 	    if (!(mask & DECOR_BELOW)) {
667 		fill_top_left = x;
668 		fill_bottom_left = x + BLOCK_SZ;
669 		fill_top_right = fill_bottom_right = -1;
670 	    } else {
671 		fill_top_right = x;
672 		fill_bottom_right = x + BLOCK_SZ;
673 	    }
674 	}
675 	if (mask & DECOR_RIGHT) {
676 	    fill_top_right = fill_bottom_right = x + BLOCK_SZ;
677 	}
678 	if (fill_top_left == -1) {
679 	    fill_top_left = fill_bottom_left = x;
680 	}
681 	if (fill_top_right == -1
682 	    && (last || more_y)) {
683 	    fill_top_right = x + BLOCK_SZ;
684 	    fill_bottom_right = x + BLOCK_SZ;
685 	}
686 	if (fill_top_right != -1) {
687 	    points[0].x = WINSCALE(X(fill_bottom_left));
688 	    points[0].y = WINSCALE(Y(y));
689 	    points[1].x = WINSCALE(X(fill_top_left));
690 	    points[1].y = WINSCALE(Y(y + BLOCK_SZ));
691 	    points[2].x = WINSCALE(X(fill_top_right));
692 	    points[2].y = WINSCALE(Y(y + BLOCK_SZ));
693 	    points[3].x = WINSCALE(X(fill_bottom_right));
694 	    points[3].y = WINSCALE(Y(y));
695 	    points[4] = points[0];
696 	    rd.fillPolygon(dpy, p_draw, gc,
697 			   points, 5,
698 			   Convex, CoordModeOrigin);
699 	    if (useErase){
700 		int left_x = MIN(fill_bottom_left, fill_top_left);
701 		int right_x = MAX(fill_bottom_right, fill_top_right);
702 		Erase_rectangle(WINSCALE(X(left_x)) - 1,
703 				WINSCALE(Y(y + BLOCK_SZ)) - 1,
704 				WINSCALE(right_x - left_x) + 4,
705 				WINSCALE(BLOCK_SZ) + 3);
706 	    }
707 	    fill_top_left =
708 	    fill_top_right =
709 	    fill_bottom_left =
710 	    fill_bottom_right = -1;
711 	}
712     }
713     if (decorTileDoit && last) {
714         XSetFillStyle(dpy, gc, FillSolid);
715     }
716 }
717 
718 
Gui_paint_setup_check(int x,int y,int xi,int yi)719 void Gui_paint_setup_check(int x, int y, int xi, int yi)
720 {
721     XPoint points[5];
722     if (!blockBitmaps) {
723 	SET_FG(colors[BLUE].pixel);
724 	points[0].x = WINSCALE(X(x+(BLOCK_SZ/2)));
725 	points[0].y = WINSCALE(Y(y));
726 	points[1].x = WINSCALE(X(x));
727 	points[1].y = WINSCALE(Y(y+BLOCK_SZ/2));
728 	points[2].x = WINSCALE(X(x+BLOCK_SZ/2));
729 	points[2].y = WINSCALE(Y(y+BLOCK_SZ));
730 	points[3].x = WINSCALE(X(x+BLOCK_SZ));
731 	points[3].y = WINSCALE(Y(y+(BLOCK_SZ/2)));
732 	points[4] = points[0];
733 
734 	if (Check_index_by_pos(xi, yi) == nextCheckPoint) {
735 	    rd.fillPolygon(dpy, p_draw, gc,
736 			   points, 5,
737 			   Convex, CoordModeOrigin);
738 	    Erase_rectangle(WINSCALE(X(x)),
739 			    WINSCALE(Y(y+BLOCK_SZ)),
740 			    WINSCALE(BLOCK_SZ),
741 			    WINSCALE(BLOCK_SZ));
742 	} else {
743 	    rd.drawLines(dpy, p_draw, gc,
744 			 points, 5, 0);
745 	    Erase_points(0, points, 5);
746 	}
747     } else {
748 	if (Check_index_by_pos(xi, yi) == nextCheckPoint) {
749 	    PaintBitmap(p_draw, BM_CHECKPOINT, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
750 		WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 1);
751 
752 	} else {
753 	    PaintBitmap(p_draw, BM_CHECKPOINT, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
754 		WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
755 
756 	}
757 	Erase_rectangle(WINSCALE(X(x)),
758 			WINSCALE(Y(y+BLOCK_SZ)),
759 			WINSCALE(BLOCK_SZ),
760 			WINSCALE(BLOCK_SZ));
761     }
762 }
763 
764 
Gui_paint_border(int x,int y,int xi,int yi)765 void Gui_paint_border(int x, int y, int xi, int yi)
766 {
767     Segment_add(wallColor,
768 		X(x), Y(y),
769 		X(xi), Y(yi));
770 }
771 
772 
Gui_paint_visible_border(int x,int y,int xi,int yi)773 void Gui_paint_visible_border(int x, int y, int xi, int yi)
774 {
775     Segment_add(hudColor,
776 		X(x), Y(y),
777 		X(x), Y(yi));
778 
779     Segment_add(hudColor,
780 		X(xi), Y(y),
781 		X(xi), Y(yi));
782 
783     Segment_add(hudColor,
784 		X(x), Y(y),
785 		X(xi), Y(y));
786 
787     Segment_add(hudColor,
788 		X(x), Y(yi),
789 		X(xi), Y(yi));
790 }
791 
792 
Gui_paint_setup_acwise_grav(int x,int y)793 void Gui_paint_setup_acwise_grav(int x, int y)
794 {
795     Arc_add(RED, X(x+5), Y(y+BLOCK_SZ-5),
796 	    BLOCK_SZ-10, BLOCK_SZ-10, 64*150, 64*300);
797     Segment_add(RED,
798 		X(x+BLOCK_SZ/2),
799 		Y(y+BLOCK_SZ-5),
800 		X(x+BLOCK_SZ/2+4),
801 		Y(y+BLOCK_SZ-1));
802     Segment_add(RED,
803 		X(x+BLOCK_SZ/2),
804 		Y(y+BLOCK_SZ-5),
805 		X(x+BLOCK_SZ/2+4),
806 		Y(y+BLOCK_SZ-9));
807 }
808 
809 
Gui_paint_setup_cwise_grav(int x,int y)810 void Gui_paint_setup_cwise_grav(int x, int y)
811 {
812     Arc_add(RED,
813 	    X(x+5), Y(y+BLOCK_SZ-5),
814 	    BLOCK_SZ-10, BLOCK_SZ-10, 64*90, 64*300);
815     Segment_add(RED,
816 		X(x+BLOCK_SZ/2),
817 		Y(y+BLOCK_SZ-5),
818 		X(x+BLOCK_SZ/2-4),
819 		Y(y+BLOCK_SZ-1));
820     Segment_add(RED,
821 		X(x+BLOCK_SZ/2),
822 		Y(y+BLOCK_SZ-5),
823 		X(x+BLOCK_SZ/2-4),
824 		Y(y+BLOCK_SZ-9));
825 }
826 
827 
Gui_paint_setup_pos_grav(int x,int y)828 void Gui_paint_setup_pos_grav(int x, int y)
829 {
830     static const int	INSIDE_BL = BLOCK_SZ - 2;
831     if (!blockBitmaps) {
832 
833     Arc_add(RED,
834 	    X(x+1), Y(y+BLOCK_SZ-1),
835 	    INSIDE_BL, INSIDE_BL, 0, 64*360);
836     Segment_add(RED,
837 	      X(x+BLOCK_SZ/2),
838 	      Y(y+5),
839 	      X(x+BLOCK_SZ/2),
840 	      Y(y+BLOCK_SZ-5));
841     Segment_add(RED,
842 		X(x+5),
843 		Y(y+BLOCK_SZ/2),
844 		X(x+BLOCK_SZ-5),
845 		Y(y+BLOCK_SZ/2));
846     } else {
847 	PaintBitmap(p_draw, BM_PLUSGRAVITY, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
848 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
849 
850     }
851 }
852 
853 
Gui_paint_setup_neg_grav(int x,int y)854 void Gui_paint_setup_neg_grav(int x, int y)
855 {
856     static const int	INSIDE_BL = BLOCK_SZ - 2;
857 
858     if (!blockBitmaps) {
859 
860 	Arc_add(RED,
861 		X(x+1), Y(y+BLOCK_SZ-1),
862 		INSIDE_BL, INSIDE_BL, 0, 64*360);
863 	Segment_add(RED,
864 		    X(x+5),
865 		    Y(y+BLOCK_SZ/2),
866 		    X(x+BLOCK_SZ-5),
867 		    Y(y+BLOCK_SZ/2));
868     } else {
869 	PaintBitmap(p_draw, BM_MINUSGRAVITY, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
870 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
871 
872     }
873 }
874 
875 
876 
Gui_paint_setup_up_grav(int x,int y)877 void Gui_paint_setup_up_grav(int x, int y)
878 {
879     Segment_add(RED,
880 		X(x+BLOCK_SZ/2),
881 		Y(y),
882 		X(x+BLOCK_SZ/2),
883 		Y(y+BLOCK_SZ));
884     Segment_add(RED,
885 		X(x+BLOCK_SZ/2),
886 		Y(y+BLOCK_SZ),
887 		X(x+BLOCK_SZ/2-10),
888 		Y(y+BLOCK_SZ-10));
889     Segment_add(RED,
890 		X(x+BLOCK_SZ/2),
891 		Y(y+BLOCK_SZ),
892 		X(x+BLOCK_SZ/2+10),
893 		Y(y+BLOCK_SZ-10));
894 }
895 
896 
897 
Gui_paint_setup_down_grav(int x,int y)898 void Gui_paint_setup_down_grav(int x, int y)
899 {
900     Segment_add(RED,
901 		X(x+BLOCK_SZ/2),
902 		Y(y),
903 		X(x+BLOCK_SZ/2),
904 		Y(y+BLOCK_SZ));
905     Segment_add(RED,
906 		X(x+BLOCK_SZ/2),
907 		Y(y),
908 		X(x+BLOCK_SZ/2-10),
909 		Y(y+10));
910     Segment_add(RED,
911 		X(x+BLOCK_SZ/2),
912 		Y(y),
913 		X(x+BLOCK_SZ/2+10),
914 		Y(y+10));
915 }
916 
917 
918 
Gui_paint_setup_right_grav(int x,int y)919 void Gui_paint_setup_right_grav(int x, int y)
920 {
921     Segment_add(RED,
922 		X(x),
923 		Y(y+BLOCK_SZ/2),
924 		X(x+BLOCK_SZ),
925 		Y(y+BLOCK_SZ/2));
926     Segment_add(RED,
927 		X(x+BLOCK_SZ),
928 		Y(y+BLOCK_SZ/2),
929 		X(x+BLOCK_SZ-10),
930 		Y(y+BLOCK_SZ/2+10));
931     Segment_add(RED,
932 		X(x+BLOCK_SZ),
933 		Y(y+BLOCK_SZ/2),
934 		X(x+BLOCK_SZ-10),
935 		Y(y+BLOCK_SZ/2-10));
936 }
937 
938 
939 
Gui_paint_setup_left_grav(int x,int y)940 void Gui_paint_setup_left_grav(int x, int y)
941 {
942     Segment_add(RED,
943 		X(x),
944 		Y(y+BLOCK_SZ/2),
945 		X(x+BLOCK_SZ),
946 		Y(y+BLOCK_SZ/2));
947     Segment_add(RED,
948 		X(x),
949 		Y(y+BLOCK_SZ/2),
950 		X(x+10),
951 		Y(y+BLOCK_SZ/2+10));
952     Segment_add(RED,
953 		X(x),
954 		Y(y+BLOCK_SZ/2),
955 		X(x+10),
956 		Y(y+BLOCK_SZ/2-10));
957 }
958 
959 
Gui_paint_setup_worm(int x,int y,int wormDrawCount)960 void Gui_paint_setup_worm(int x, int y, int wormDrawCount)
961 {
962     if (!blockBitmaps) {
963 	static const int	INSIDE_BL = BLOCK_SZ - 2;
964 	static int wormOffset[8][3] = {
965 	    { 10, 10, 10 },
966 	    { 5, 10, 10 },
967 	    { 0, 10, 10 },
968 	    { 0, 5, 10 },
969 	    { 0, 0, 10 },
970 	    { 5, 0, 10 },
971 	    { 10, 0, 10 },
972 	    { 10, 5, 10 }
973 	};
974 #define _O	wormOffset[wormDrawCount]
975 
976 	SET_FG(colors[RED].pixel);
977 	Arc_add(RED,
978 		X(x) + 0, Y(y + BLOCK_SZ) + 0,
979 		INSIDE_BL - 0, INSIDE_BL - 0, 0, 64 * 360);
980 
981 	Arc_add(RED,
982 		X(x) + _O[0], Y(y + BLOCK_SZ) + _O[1],
983 		INSIDE_BL - _O[2], INSIDE_BL - _O[2], 0, 64 * 360);
984 
985 	Arc_add(RED,
986 		X(x) + _O[0] * 2, Y(y + BLOCK_SZ) + _O[1] * 2,
987 		INSIDE_BL - _O[2] * 2, INSIDE_BL - _O[2] * 2, 0, 64 * 360);
988     }
989     else {
990 	PaintBitmap(p_draw, BM_WORMHOLE, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
991 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), wormDrawCount);
992     }
993 }
994 
995 
Gui_paint_setup_item_concentrator(int x,int y)996 void Gui_paint_setup_item_concentrator(int x, int y)
997 {
998     static struct concentrator_triangle {
999 	int		radius;
1000 	int		displ;
1001 	int		dir_off;
1002 	int		rot_speed;
1003 	int		rot_dir;
1004     } tris[] = {
1005 #if 0
1006 	{ 14, 3, 0, 1, 0 },
1007 	{ 11, 5, 3, 2, 0 },
1008 	{  7, 8, 5, 3, 0 },
1009 #else
1010 	{  7, 3, 0, 3, 0 },
1011 	{ 11, 5, 3, 3, 0 },
1012 	{ 14, 8, 5, 3, 0 },
1013 #endif
1014     };
1015     static unsigned	rot_dir;
1016     static long		concentratorloop;
1017     unsigned		rdir, tdir;
1018     int			i, cx, cy;
1019     XPoint		pts[4];
1020     if (!blockBitmaps) {
1021 	SET_FG(colors[RED].pixel);
1022 	if (concentratorloop != loops) {
1023 	    concentratorloop = loops;
1024 	    rot_dir += 5;
1025 	    for (i = 0; i < NELEM(tris); i++) {
1026 		tris[i].rot_dir += tris[i].rot_speed;
1027 	    }
1028 	}
1029 	for (i = 0; i < NELEM(tris); i++) {
1030 	    /* I'll bet you didn't know that floating point math
1031 	       is faster than integer math on a pentium
1032 	       (and for some reason the UNIX way rounds off too much) */
1033 	    rdir = MOD2(rot_dir + tris[i].dir_off, RES);
1034 	    cx = (int)(X(x + BLOCK_SZ / 2)
1035 		+ tris[i].displ * tcos(rdir));
1036 	    cy = (int)(Y(y + BLOCK_SZ / 2)
1037 		+ tris[i].displ * tsin(rdir));
1038 	    tdir = MOD2(tris[i].rot_dir, RES);
1039 	    pts[0].x = WINSCALE(cx + (int)(tris[i].radius * tcos(tdir)));
1040 	    pts[0].y = WINSCALE(cy + (int)(tris[i].radius * tsin(tdir)));
1041 	    pts[1].x = WINSCALE(cx + (int)(tris[i].radius
1042 			  * tcos(MOD2(tdir + RES/3, RES))));
1043 	    pts[1].y = WINSCALE(cy + (int)(tris[i].radius
1044 			  * tsin(MOD2(tdir + RES/3, RES))));
1045 	    pts[2].x = WINSCALE(cx + (int)(tris[i].radius
1046 			  * tcos(MOD2(tdir + 2*RES/3, RES))));
1047 	    pts[2].y = WINSCALE(cy + (int)(tris[i].radius
1048 			  * tsin(MOD2(tdir + 2*RES/3, RES))));
1049 	    /* Trace("DC: %d cx=%d/%d %d/%d %d/%d %d/%d %d/%d\n",
1050 		    i, cx, cy, pts[0].x, pts[0].y,
1051 		    pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y); */
1052 
1053 	    pts[3] = pts[0];
1054 	    rd.drawLines(dpy, p_draw, gc,
1055 			 pts, NELEM(pts), CoordModeOrigin);
1056 	    Erase_points(0, pts, NELEM(pts));
1057 	}
1058     } else {
1059 	PaintBitmap(p_draw, BM_CONCENTRATOR, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1060 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), (loops + (x + x * y)) % 32);
1061 
1062     }
1063 }
1064 
1065 
Gui_paint_setup_asteroid_concentrator(int x,int y)1066 void Gui_paint_setup_asteroid_concentrator(int x, int y)
1067 {
1068     static struct concentrator_square {
1069 	int		size;
1070 	int		displ;
1071 	int		dir_off;
1072 	int		rot_speed;
1073 	int		rot_dir;
1074     } sqrs[] = {
1075 #if 0
1076 	{ 16, 3, 0, 1, 0 },
1077 	{ 12, 5, 3, 2, 0 },
1078 	{  8, 8, 5, 3, 0 },
1079 #else
1080 	{  8, 3, 0, 3, 0 },
1081 	{ 12, 5, 3, 3, 0 },
1082 	{ 16, 8, 5, 3, 0 },
1083 #endif
1084     };
1085     static unsigned	rot_dir;
1086     static long		concentratorloop;
1087     unsigned		rdir, tdir;
1088     int			i, cx, cy;
1089     XPoint		pts[5];
1090     if (!blockBitmaps) {
1091 	SET_FG(colors[RED].pixel);
1092 	if (concentratorloop != loops) {
1093 	    concentratorloop = loops;
1094 	    rot_dir += 5;
1095 	    for (i = 0; i < NELEM(sqrs); i++) {
1096 		sqrs[i].rot_dir += sqrs[i].rot_speed;
1097 	    }
1098 	}
1099 	for (i = 0; i < NELEM(sqrs); i++) {
1100 	    /* I'll bet you didn't know that floating point math
1101 	       is faster than integer math on a pentium
1102 	       (and for some reason the UNIX way rounds off too much) */
1103 	    rdir = MOD2(rot_dir + sqrs[i].dir_off, RES);
1104 	    cx = (int)(X(x + BLOCK_SZ / 2)
1105 		+ sqrs[i].displ * tcos(rdir));
1106 	    cy = (int)(Y(y + BLOCK_SZ / 2)
1107 		+ sqrs[i].displ * tsin(rdir));
1108 	    tdir = MOD2(sqrs[i].rot_dir, RES);
1109 	    pts[0].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(tdir)));
1110 	    pts[0].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(tdir)));
1111 	    pts[1].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + RES/4, RES))));
1112 	    pts[1].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + RES/4, RES))));
1113 	    pts[2].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + 2*RES/4, RES))));
1114 	    pts[2].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + 2*RES/4, RES))));
1115 		pts[3].x = WINSCALE(cx + (int)(sqrs[i].size * tcos(MOD2(tdir + 3*RES/4, RES))));
1116 	    pts[3].y = WINSCALE(cy + (int)(sqrs[i].size * tsin(MOD2(tdir + 3*RES/4, RES))));
1117 	    /* Trace("DC: %d cx=%d/%d %d/%d %d/%d %d/%d %d/%d\n",
1118 		    i, cx, cy, pts[0].x, pts[0].y,
1119 		    pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y); */
1120 
1121 	    pts[4] = pts[0];
1122 	    rd.drawLines(dpy, p_draw, gc,
1123 			 pts, NELEM(pts), CoordModeOrigin);
1124 	    Erase_points(0, pts, NELEM(pts));
1125 	}
1126     } else {
1127 	PaintBitmap(p_draw, BM_ASTEROIDCONC, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1128 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), (loops + (x + x * y)) % 32);
1129 
1130     }
1131 }
1132 
1133 
Gui_paint_decor_dot(int x,int y,int size)1134 void Gui_paint_decor_dot(int x, int y, int size)
1135 {
1136     Rectangle_add(BLUE, X(x + BLOCK_SZ / 2) - (map_point_size >> 1),
1137 		  Y(y + BLOCK_SZ / 2) - (map_point_size >> 1),
1138 		  size, size);
1139 }
1140 
1141 
Gui_paint_setup_target(int x,int y,int target,int damage,bool own)1142 void Gui_paint_setup_target(int x, int y, int target, int damage, bool own)
1143 {
1144     int	    size, a1, a2, b1, b2, color;
1145     char    s[2];
1146 
1147     color = own ? BLUE : RED;
1148 
1149     SET_FG(colors[color].pixel);
1150 
1151     a1 = X(x);
1152     b1 = Y(y+BLOCK_SZ);
1153     a2 = a1 + BLOCK_SZ;
1154     b2 = b1 + BLOCK_SZ;
1155     Segment_add(color, a1, b1, a1, b2);
1156     Segment_add(color, a2, b1, a2, b2);
1157     Segment_add(color, a1, b1, a2, b1);
1158     Segment_add(color, a1, b2, a2, b2);
1159 
1160     rd.drawRectangle(dpy, p_draw, gc,
1161 		     WINSCALE(X(x+(BLOCK_SZ+2)/4)),
1162 		     WINSCALE(Y(y+3*BLOCK_SZ/4)),
1163 		     WINSCALE(BLOCK_SZ/2),
1164 		     WINSCALE(BLOCK_SZ/2));
1165     Erase_4point(WINSCALE(X(x+(BLOCK_SZ+2)/4)),
1166 		 WINSCALE(Y(y+3*BLOCK_SZ/4)),
1167 		 WINSCALE(BLOCK_SZ/2), WINSCALE(BLOCK_SZ/2));
1168 
1169     if (BIT(Setup->mode, TEAM_PLAY)) {
1170 	s[0] = '0' + target; s[1] = '\0';
1171 	size = XTextWidth(gameFont, s, 1);
1172 	rd.drawString(dpy, p_draw, gc,
1173 		      WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1174 		      WINSCALE(Y(y + BLOCK_SZ/2))
1175 			+ gameFont->ascent/2,
1176 		      s, 1);
1177 	Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2)) - size/2-1,
1178 			WINSCALE(Y(y + BLOCK_SZ/2))
1179 				+ gameFont->ascent/2
1180 				- gameFont->ascent - 1,
1181 			size + 2,
1182 			gameFont->ascent+ gameFont->descent+ 2);
1183     }
1184 
1185     if (damage != TARGET_DAMAGE) {
1186 	size = (damage * BLOCK_SZ) / (TARGET_DAMAGE * 2);
1187 	a1 = x + size;
1188 	a2 = y + size;
1189 	b1 = x + (BLOCK_SZ - size);
1190 	b2 = y + (BLOCK_SZ - size);
1191 
1192 	Segment_add(RED,
1193 		    X(a1), Y(a2),
1194 		    X(b1), Y(b2));
1195 
1196 	Segment_add(RED,
1197 		    X(a1), Y(b2),
1198 		    X(b1), Y(a2));
1199     }
1200 }
1201 
1202 
Gui_paint_setup_treasure(int x,int y,int treasure,bool own)1203 void Gui_paint_setup_treasure(int x, int y, int treasure, bool own)
1204 {
1205     if (!blockBitmaps) {
1206 	char    s[2];
1207 	int	    color;
1208 	int	    size;
1209 	color = own ? BLUE : RED;
1210 
1211 	SET_FG(colors[color].pixel);
1212 	Segment_add(color,
1213 		    X(x),Y(y),
1214 		    X(x),Y(y + BLOCK_SZ/2));
1215 	Segment_add(color,
1216 		    X(x + BLOCK_SZ),Y(y),
1217 		    X(x + BLOCK_SZ),
1218 		    Y(y + BLOCK_SZ/2));
1219 	Segment_add(color,
1220 		    X(x),Y(y),
1221 		    X(x + BLOCK_SZ),Y(y));
1222 	Arc_add(color,
1223 		X(x),
1224 		Y(y + BLOCK_SZ),
1225 		BLOCK_SZ, BLOCK_SZ, 0, 64*180);
1226 	if (BIT(Setup->mode, TEAM_PLAY)) {
1227 	    s[1] = '\0'; s[0] = '0' + treasure;
1228 	    size = XTextWidth(gameFont, s, 1);
1229 	    rd.drawString(dpy, p_draw, gc,
1230 			  WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1231 			  WINSCALE(Y(y + 2*BALL_RADIUS)), s, 1);
1232 	    Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2)) - size/2 - 1,
1233 			    WINSCALE(Y(y + 2*BALL_RADIUS))
1234 			      - gameFont->ascent - 1,
1235 			    size + 2,
1236 			    gameFont->ascent+ gameFont->descent+ 2);
1237 	}
1238     }
1239     else {
1240 	char    s[2];
1241 	int	    size;
1242 
1243 	int type;
1244 	int	    color;
1245 
1246 	type = own ? BM_HOLDER_FRIEND : BM_HOLDER_ENEMY;
1247 
1248 	PaintBitmap(p_draw, type, WINSCALE(X(x)), WINSCALE(Y(y + BLOCK_SZ)),
1249 		    WINSCALE(BLOCK_SZ), WINSCALE(BLOCK_SZ), 0);
1250 
1251 	if (BIT(Setup->mode, TEAM_PLAY)) {
1252 	    color = own ? BLUE : RED;
1253             SET_FG(colors[color].pixel);
1254 
1255 	    s[1] = '\0'; s[0] = '0' + treasure;
1256 	    size = XTextWidth(gameFont, s, 1);
1257 	    rd.drawString(dpy, p_draw, gc,
1258 			  WINSCALE(X(x + BLOCK_SZ/2)) - size/2,
1259 			  WINSCALE(Y(y + BALL_RADIUS + 5)), s, 1);
1260 	    Erase_rectangle(WINSCALE(X(x + BLOCK_SZ/2 )) - size/2 - 1,
1261 			    WINSCALE(Y(y + BALL_RADIUS + 5))
1262 			      - gameFont->ascent - 1,
1263 			    size + 2,
1264 			    gameFont->ascent+ gameFont->descent+ 2);
1265 	}
1266 
1267     }
1268 }
1269 
1270