1 /* $Id: paintdata.c,v 5.9 2002/04/13 16:10:59 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 <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <math.h>
30 
31 #ifndef _WINDOWS
32 # include <unistd.h>
33 # include <X11/Xlib.h>
34 #endif
35 
36 #ifdef _WINDOWS
37 # include "NT/winX.h"
38 #endif
39 
40 #include "version.h"
41 #include "config.h"
42 #include "const.h"
43 #include "error.h"
44 #include "bit.h"
45 #include "client.h"
46 #include "setup.h"
47 #include "rules.h"
48 #include "paint.h"
49 #include "paintdata.h"
50 #include "record.h"
51 #include "xinit.h"
52 #include "protoclient.h"
53 #include "dbuff.h"
54 #include "commonproto.h"
55 
56 char paintdata_version[] = VERSION;
57 
58 refuel_t	*refuel_ptr;
59 int		 num_refuel, max_refuel;
60 connector_t	*connector_ptr;
61 int		 num_connector, max_connector;
62 laser_t		*laser_ptr;
63 int		 num_laser, max_laser;
64 missile_t	*missile_ptr;
65 int		 num_missile, max_missile;
66 ball_t		*ball_ptr;
67 int		 num_ball, max_ball;
68 ship_t		*ship_ptr;
69 int		 num_ship, max_ship;
70 mine_t		*mine_ptr;
71 int		 num_mine, max_mine;
72 itemtype_t	*itemtype_ptr;
73 int		 num_itemtype, max_itemtype;
74 ecm_t		*ecm_ptr;
75 int		 num_ecm, max_ecm;
76 trans_t		*trans_ptr;
77 int		 num_trans, max_trans;
78 paused_t	*paused_ptr;
79 int		 num_paused, max_paused;
80 radar_t		*radar_ptr;
81 int		 num_radar, max_radar;
82 vcannon_t	*vcannon_ptr;
83 int		 num_vcannon, max_vcannon;
84 vfuel_t		*vfuel_ptr;
85 int		 num_vfuel, max_vfuel;
86 vbase_t		*vbase_ptr;
87 int		 num_vbase, max_vbase;
88 debris_t	*debris_ptr[DEBRIS_TYPES];
89 int		 num_debris[DEBRIS_TYPES],
90 		 max_debris[DEBRIS_TYPES];
91 debris_t	*fastshot_ptr[DEBRIS_TYPES * 2];
92 int		 num_fastshot[DEBRIS_TYPES * 2],
93 		 max_fastshot[DEBRIS_TYPES * 2];
94 vdecor_t	*vdecor_ptr;
95 int		 num_vdecor, max_vdecor;
96 wreckage_t	*wreckage_ptr;
97 int		 num_wreckage, max_wreckage;
98 asteroid_t	*asteroid_ptr;
99 int		 num_asteroids, max_asteroids;
100 wormhole_t	*wormhole_ptr;
101 int		 num_wormholes, max_wormholes;
102 
103 long		time_left = -1;
104 long		start_loops, end_loops;
105 
106 XRectangle	*rect_ptr[MAX_COLORS];
107 int		num_rect[MAX_COLORS], max_rect[MAX_COLORS];
108 XArc		*arc_ptr[MAX_COLORS];
109 int		num_arc[MAX_COLORS], max_arc[MAX_COLORS];
110 XSegment	*seg_ptr[MAX_COLORS];
111 int		num_seg[MAX_COLORS], max_seg[MAX_COLORS];
112 
113 int		eyesId;		/* Player we get frame updates for */
114 short		snooping;	/* are we snooping on someone else? */
115 
116 unsigned long	current_foreground;
117 
118 erase_t		erase[2], *erp;
119 
Erase_do_start(void)120 void Erase_do_start(void)
121 {
122     int			i;
123 
124     if (damaged > 0) {
125 	error("BUG: Erase_start while damaged");
126 	return;
127     }
128 
129     if (erase[0].flags == 0) {
130 	printf("ERASE is On!\n");
131 	erp = &erase[0];
132     }
133     if (BIT(erp->flags, ERASE_INITIALIZED) == 0) {
134 	SET_FG(colors[BLACK].pixel);
135 	XFillRectangle(dpy, p_draw, gc, 0, 0, draw_width, draw_height);
136 	SET_BIT(erp->flags, ERASE_INITIALIZED);
137     }
138     erp->num_rect = 0;
139     erp->num_arc = 0;
140     for (i = 0; i <= MAX_LINE_WIDTH; i++) {
141 	erp->num_seg[i] = 0;
142     }
143 }
144 
Erase_do_end(void)145 void Erase_do_end(void)
146 {
147     int			i,
148 			linewidth = false;
149 
150     if (damaged > 0) {
151 	error("BUG: Erase_do_end while damaged");
152 	return;
153     }
154 #ifndef _WINDOWS
155     /* BG fix 2000-03-19 use same erase buffer if not color switching. */
156     if (dbuf_state->type == COLOR_SWITCH) {
157 	if (erp == &erase[0]) {
158 	    erp = &erase[1];
159 	} else {
160 	    erp = &erase[0];
161 	}
162     }
163 #endif
164     SET_FG(colors[BLACK].pixel);
165 
166     if (erp->num_rect != 0) {
167 	XFillRectangles(dpy, p_draw, gc, erp->rect_ptr, erp->num_rect);
168 	UNEXPAND(erp->rect_ptr, erp->num_rect, erp->max_rect);
169     }
170     if (erp->num_arc != 0) {
171 	XDrawArcs(dpy, p_draw, gc, erp->arc_ptr, erp->num_arc);
172 	UNEXPAND(erp->arc_ptr, erp->num_arc, erp->max_arc);
173     }
174     for (i = 0; i <= MAX_LINE_WIDTH; i++) {
175 	if (erp->num_seg[i] != 0) {
176 	    XSetLineAttributes(dpy, gc, i,
177 			       LineSolid, CapProjecting, JoinMiter);
178 	    linewidth = true;
179 	    XDrawSegments(dpy, p_draw, gc, erp->seg_ptr[i], erp->num_seg[i]);
180 	    UNEXPAND(erp->seg_ptr[i], erp->num_seg[i], erp->max_seg[i]);
181 	}
182     }
183     if (linewidth == true) {
184 	XSetLineAttributes(dpy, gc, 0,
185 			   LineSolid, CapButt, JoinMiter);
186     }
187 }
188 
Erase_do_rectangle(int x,int y,int width,int height)189 void Erase_do_rectangle(int x, int y, int width, int height)
190 {
191     XRectangle		*p;
192 
193     EXPAND(erp->rect_ptr, erp->num_rect, erp->max_rect, XRectangle, 1);
194     p = &erp->rect_ptr[erp->num_rect++];
195     p->x = x;
196     p->y = y;
197     p->width = width;
198     p->height = height;
199 }
200 
Erase_do_rectangles(XRectangle * rectp,int n)201 void Erase_do_rectangles(XRectangle *rectp, int n)
202 {
203     EXPAND(erp->rect_ptr, erp->num_rect, erp->max_rect, XRectangle, n);
204     memcpy(&erp->rect_ptr[erp->num_rect], rectp, n * sizeof(XRectangle));
205     erp->num_rect += n;
206 }
207 
Erase_do_arc(int x,int y,int width,int height,int angle1,int angle2)208 void Erase_do_arc(int x, int y, int width, int height,
209 		      int angle1, int angle2)
210 {
211     XArc		*p;
212 
213     EXPAND(erp->arc_ptr, erp->num_arc, erp->max_arc, XArc, 1);
214     p = &erp->arc_ptr[erp->num_arc++];
215     p->x = x;
216     p->y = y;
217     p->width = width;
218     p->height = height;
219     p->angle1 = angle1;
220     p->angle2 = angle2;
221 }
222 
Erase_do_arcs(XArc * arcp,int n)223 void Erase_do_arcs(XArc *arcp, int n)
224 {
225     EXPAND(erp->arc_ptr, erp->num_arc, erp->max_arc, XArc, n);
226     memcpy(&erp->arc_ptr[erp->num_arc], arcp, n * sizeof(XArc));
227     erp->num_arc += n;
228 }
229 
Erase_do_segment(int width,int x1,int y1,int x2,int y2)230 void Erase_do_segment(int width, int x1, int y1, int x2, int y2)
231 {
232     XSegment		*p;
233 
234     EXPAND(erp->seg_ptr[width], erp->num_seg[width], erp->max_seg[width],
235 	   XSegment, 1);
236     p = &erp->seg_ptr[width][erp->num_seg[width]++];
237     p->x1 = x1;
238     p->y1 = y1;
239     p->x2 = x2;
240     p->y2 = y2;
241 }
242 
Erase_do_segments(XSegment * segp,int n)243 void Erase_do_segments(XSegment *segp, int n)
244 {
245     EXPAND(erp->seg_ptr[0], erp->num_seg[0], erp->max_seg[0],
246 	   XSegment, n);
247     memcpy(&erp->seg_ptr[0][erp->num_seg[0]], segp, n * sizeof(XSegment));
248     erp->num_seg[0] += n;
249 }
250 
Erase_do_points(int width,XPoint * pointp,int n)251 void Erase_do_points(int width, XPoint *pointp, int n)
252 {
253     XSegment		*p;
254     int			i;
255 
256     EXPAND(erp->seg_ptr[width], erp->num_seg[width], erp->max_seg[width],
257 	   XSegment, n - 1);
258     p = &erp->seg_ptr[width][erp->num_seg[width]];
259     for (i = 1; i < n; i++) {
260 	p->x1 = pointp->x;
261 	p->y1 = pointp->y;
262 	pointp++;
263 	p->x2 = pointp->x;
264 	p->y2 = pointp->y;
265 	p++;
266     }
267     erp->num_seg[width] += n - 1;
268 }
269 
Erase_do_4point(int x,int y,int width,int height)270 void Erase_do_4point(int x, int y, int width, int height)
271 {
272     XSegment		*p;
273 
274     EXPAND(erp->seg_ptr[0], erp->num_seg[0], erp->max_seg[0],
275 	   XSegment, 4);
276     p = &erp->seg_ptr[0][erp->num_seg[0]];
277     p->x1 = x;
278     p->y1 = y;
279     p->x2 = x + width;
280     p->y2 = y;
281     p++;
282     p->x1 = x + width;
283     p->y1 = y;
284     p->x2 = x + width;
285     p->y2 = y + height;
286     p++;
287     p->x1 = x + width;
288     p->y1 = y + height;
289     p->x2 = x;
290     p->y2 = y + height;
291     p++;
292     p->x1 = x;
293     p->y1 = y + height;
294     p->x2 = x;
295     p->y2 = y;
296     p++;
297     erp->num_seg[0] += 4;
298 }
299 
Rectangle_start(void)300 void Rectangle_start(void)
301 {
302     int i;
303 
304     for (i = 0; i < maxColors; i++) {
305 	num_rect[i] = 0;
306     }
307 }
308 
Rectangle_end(void)309 void Rectangle_end(void)
310 {
311     int i;
312 
313     for (i = 0; i < maxColors; i++) {
314 	if (num_rect[i] > 0) {
315 	    SET_FG(colors[i].pixel);
316 	    rd.fillRectangles(dpy, p_draw, gc, rect_ptr[i], num_rect[i]);
317 	    Erase_rectangles(rect_ptr[i], num_rect[i]);
318 	    RELEASE(rect_ptr[i], num_rect[i], max_rect[i]);
319 	}
320     }
321 }
322 
Rectangle_add(int color,int x,int y,int width,int height)323 int Rectangle_add(int color, int x, int y, int width, int height)
324 {
325     XRectangle		t;
326 
327     t.x = WINSCALE(x);
328     t.y = WINSCALE(y);
329     t.width = WINSCALE(width);
330     t.height = WINSCALE(height);
331 
332     STORE(XRectangle, rect_ptr[color], num_rect[color], max_rect[color], t);
333     return 0;
334 }
335 
Arc_start(void)336 void Arc_start(void)
337 {
338     int i;
339 
340     for (i = 0; i < maxColors; i++) {
341 	num_arc[i] = 0;
342     }
343 }
344 
Arc_end(void)345 void Arc_end(void)
346 {
347     int i;
348 
349     for (i = 0; i < maxColors; i++) {
350 	if (num_arc[i] > 0) {
351 	    SET_FG(colors[i].pixel);
352 	    rd.drawArcs(dpy, p_draw, gc, arc_ptr[i], num_arc[i]);
353 	    Erase_arcs(arc_ptr[i], num_arc[i]);
354 	    RELEASE(arc_ptr[i], num_arc[i], max_arc[i]);
355 	}
356     }
357 }
358 
Arc_add(int color,int x,int y,int width,int height,int angle1,int angle2)359 int Arc_add(int color,
360 	    int x, int y,
361 	    int width, int height,
362 	    int angle1, int angle2)
363 {
364     XArc t;
365 
366 #ifndef WINDOWSCALING
367     t.x = x;
368     t.y = y;
369     t.width = width;
370     t.height = height;
371 #else
372     t.x = WINSCALE(x);
373     t.y = WINSCALE(y);
374     t.width = WINSCALE(width+x) - t.x;
375     t.height = WINSCALE(height+y) - t.y;
376 #endif
377     t.angle1 = angle1;
378     t.angle2 = angle2;
379     STORE(XArc, arc_ptr[color], num_arc[color], max_arc[color], t);
380     return 0;
381 }
382 
Segment_start(void)383 void Segment_start(void)
384 {
385     int i;
386 
387     for (i = 0; i < maxColors; i++) {
388 	num_seg[i] = 0;
389     }
390 }
391 
Segment_end(void)392 void Segment_end(void)
393 {
394     int i;
395 
396     for (i = 0; i < maxColors; i++) {
397 	if (num_seg[i] > 0) {
398 	    SET_FG(colors[i].pixel);
399 	    rd.drawSegments(dpy, p_draw, gc,
400 		seg_ptr[i], num_seg[i]);
401 	    Erase_segments(seg_ptr[i], num_seg[i]);
402 	    RELEASE(seg_ptr[i], num_seg[i], max_seg[i]);
403 	}
404     }
405 }
406 
Segment_add(int color,int x1,int y1,int x2,int y2)407 int Segment_add(int color, int x1, int y1, int x2, int y2)
408 {
409     XSegment t;
410 
411     t.x1 = WINSCALE(x1);
412     t.y1 = WINSCALE(y1);
413     t.x2 = WINSCALE(x2);
414     t.y2 = WINSCALE(y2);
415     STORE(XSegment, seg_ptr[color], num_seg[color], max_seg[color], t);
416     return 0;
417 }
418 
Handle_start(long server_loops)419 int Handle_start(long server_loops)
420 {
421     int			i;
422 
423     start_loops = server_loops;
424 
425     num_refuel = 0;
426     num_connector = 0;
427     num_missile = 0;
428     num_ball = 0;
429     num_ship = 0;
430     num_mine = 0;
431     num_itemtype = 0;
432     num_ecm = 0;
433     num_trans = 0;
434     num_paused = 0;
435     num_radar = 0;
436     num_vcannon = 0;
437     num_vfuel = 0;
438     num_vbase = 0;
439     num_vdecor = 0;
440     for (i = 0; i < DEBRIS_TYPES; i++) {
441 	num_debris[i] = 0;
442     }
443 
444     damaged = 0;
445     destruct = 0;
446     shutdown_delay = 0;
447     shutdown_count = -1;
448     eyesId = (self != NULL) ? self->id : 0;
449     thrusttime = -1;
450     shieldtime = -1;
451     phasingtime = -1;
452     return 0;
453 }
454 
Handle_end(long server_loops)455 int Handle_end(long server_loops)
456 {
457     end_loops = server_loops;
458     snooping = self && (eyesId != self->id);
459     Paint_frame();
460     return 0;
461 }
462 
Handle_self_items(u_byte * newNumItems)463 int Handle_self_items(u_byte *newNumItems)
464 {
465     memcpy(numItems, newNumItems, NUM_ITEMS * sizeof(u_byte));
466     return 0;
467 }
468 
Handle_self(int x,int y,int vx,int vy,int newHeading,float newPower,float newTurnspeed,float newTurnresistance,int newLockId,int newLockDist,int newLockBearing,int newNextCheckPoint,int newAutopilotLight,u_byte * newNumItems,int newCurrentTank,int newFuelSum,int newFuelMax,int newPacketSize)469 int Handle_self(int x, int y, int vx, int vy, int newHeading,
470 		float newPower, float newTurnspeed, float newTurnresistance,
471 		int newLockId, int newLockDist, int newLockBearing,
472 		int newNextCheckPoint, int newAutopilotLight,
473 		u_byte *newNumItems, int newCurrentTank,
474 		int newFuelSum, int newFuelMax, int newPacketSize)
475 {
476     pos.x = x;
477     pos.y = y;
478     vel.x = vx;
479     vel.y = vy;
480     heading = newHeading;
481     displayedPower = newPower;
482     displayedTurnspeed = newTurnspeed;
483     displayedTurnresistance = newTurnresistance;
484     lock_id = newLockId;
485     lock_dist = newLockDist;
486     lock_dir = newLockBearing;
487     nextCheckPoint = newNextCheckPoint;
488     autopilotLight = newAutopilotLight;
489     memcpy(numItems, newNumItems, NUM_ITEMS * sizeof(u_byte));
490     fuelCurrent = newCurrentTank;
491     if (newFuelSum > fuelSum && selfVisible != 0) {
492 	fuelCount = FUEL_NOTIFY;
493     }
494     fuelSum = newFuelSum;
495     fuelMax = newFuelMax;
496     selfVisible = 0;
497     if (newPacketSize + 16 < packet_size) {
498 	packet_size -= 16;
499     } else {
500 	packet_size = newPacketSize;
501     }
502 
503     world.x = pos.x - (ext_view_width / 2);
504     world.y = pos.y - (ext_view_height / 2);
505     realWorld = world;
506     if (BIT(Setup->mode, WRAP_PLAY)) {
507 	if (world.x < 0 && world.x + ext_view_width < Setup->width) {
508 	    world.x += Setup->width;
509 	}
510 	else if (world.x > 0 && world.x + ext_view_width >= Setup->width) {
511 	    realWorld.x -= Setup->width;
512 	}
513 	if (world.y < 0 && world.y + ext_view_height < Setup->height) {
514 	    world.y += Setup->height;
515 	}
516 	else if (world.y > 0 && world.y + ext_view_height >= Setup->height) {
517 	    realWorld.y -= Setup->height;
518 	}
519     }
520     return 0;
521 }
522 
523 
Handle_eyes(int id)524 int Handle_eyes(int id)
525 {
526     eyesId = id;
527     return 0;
528 }
529 
Handle_damaged(int dam)530 int Handle_damaged(int dam)
531 {
532     damaged = dam;
533     return 0;
534 }
535 
Handle_modifiers(char * m)536 int Handle_modifiers(char *m)
537 {
538     strlcpy(mods, m, MAX_CHARS);
539     return 0;
540 }
541 
Handle_destruct(int count)542 int Handle_destruct(int count)
543 {
544     destruct = count;
545     return 0;
546 }
547 
548 
Handle_shutdown(int count,int delay)549 int Handle_shutdown(int count, int delay)
550 {
551     shutdown_count = count;
552     shutdown_delay = delay;
553     return 0;
554 }
555 
Handle_thrusttime(int count,int max)556 int Handle_thrusttime(int count, int max)
557 {
558     thrusttime = count;
559     thrusttimemax = max;
560     return 0;
561 }
562 
Handle_shieldtime(int count,int max)563 int Handle_shieldtime(int count, int max)
564 {
565     shieldtime = count;
566     shieldtimemax = max;
567     return 0;
568 }
569 
Handle_phasingtime(int count,int max)570 int Handle_phasingtime(int count, int max)
571 {
572     phasingtime = count;
573     phasingtimemax = max;
574     return 0;
575 }
576 
Handle_rounddelay(int count,int max)577 int Handle_rounddelay(int count, int max)
578 {
579 	roundDelay = count;
580 	roundDelayMax = max;
581 	return(0);
582 }
583 
Handle_refuel(int x0,int y0,int x1,int y1)584 int Handle_refuel(int x0, int y0, int x1, int y1)
585 {
586     refuel_t	t;
587 
588     t.x0 = x0;
589     t.x1 = x1;
590     t.y0 = y0;
591     t.y1 = y1;
592     STORE(refuel_t, refuel_ptr, num_refuel, max_refuel, t);
593     return 0;
594 }
595 
Handle_connector(int x0,int y0,int x1,int y1,int tractor)596 int Handle_connector(int x0, int y0, int x1, int y1, int tractor)
597 {
598     connector_t	t;
599 
600     t.x0 = x0;
601     t.x1 = x1;
602     t.y0 = y0;
603     t.y1 = y1;
604     t.tractor = tractor;
605     STORE(connector_t, connector_ptr, num_connector, max_connector, t);
606     return 0;
607 }
608 
Handle_laser(int color,int x,int y,int len,int dir)609 int Handle_laser(int color, int x, int y, int len, int dir)
610 {
611     laser_t	t;
612 
613     t.color = color;
614     t.x = x;
615     t.y = y;
616     t.len = len;
617     t.dir = dir;
618     STORE(laser_t, laser_ptr, num_laser, max_laser, t);
619     return 0;
620 }
621 
Handle_missile(int x,int y,int len,int dir)622 int Handle_missile(int x, int y, int len, int dir)
623 {
624     missile_t	t;
625 
626     t.x = x;
627     t.y = y;
628     t.dir = dir;
629     t.len = len;
630     STORE(missile_t, missile_ptr, num_missile, max_missile, t);
631     return 0;
632 }
633 
Handle_ball(int x,int y,int id)634 int Handle_ball(int x, int y, int id)
635 {
636     ball_t	t;
637 
638     t.x = x;
639     t.y = y;
640     t.id = id;
641     STORE(ball_t, ball_ptr, num_ball, max_ball, t);
642     return 0;
643 }
644 
Handle_ship(int x,int y,int id,int dir,int shield,int cloak,int eshield,int phased,int deflector)645 int Handle_ship(int x, int y, int id, int dir, int shield, int cloak, int eshield,
646 				int phased, int deflector)
647 {
648     ship_t	t;
649 
650     t.x = x;
651     t.y = y;
652     t.id = id;
653     t.dir = dir;
654     t.shield = shield;
655     t.cloak = cloak;
656     t.eshield = eshield;
657     t.phased = phased;
658     t.deflector = deflector;
659     STORE(ship_t, ship_ptr, num_ship, max_ship, t);
660 
661     /* if we see a ship in the center of the display, we may be watching
662      * it, especially if it's us!  consider any ship there to be our eyes
663      * until we see a ship that really is us.
664      * BG: XXX there was a bug here.  self was dereferenced at "self->id"
665      * while self could be NULL here.
666      */
667     if (!selfVisible && ((x == pos.x && y == pos.y) || (self && id == self->id))) {
668 	int radarx, radary;
669         eyesId = id;
670 	selfVisible = (self && (id == self->id));
671 	radarx = (int)((double)(x * RadarWidth) / Setup->width + 0.5);
672 	radary = (int)((double)(y * RadarHeight) / Setup->height + 0.5);
673 	return Handle_radar(radarx, radary, 3);
674     }
675 
676     return 0;
677 }
678 
Handle_mine(int x,int y,int teammine,int id)679 int Handle_mine(int x, int y, int teammine, int id)
680 {
681     mine_t	t;
682 
683     t.x = x;
684     t.y = y;
685     t.teammine = teammine;
686     t.id = id;
687     STORE(mine_t, mine_ptr, num_mine, max_mine, t);
688     return 0;
689 }
690 
Handle_item(int x,int y,int type)691 int Handle_item(int x, int y, int type)
692 {
693     itemtype_t	t;
694 
695     t.x = x;
696     t.y = y;
697     t.type = type;
698     STORE(itemtype_t, itemtype_ptr, num_itemtype, max_itemtype, t);
699     return 0;
700 }
701 
702 #define STORE_DEBRIS(typ_e, _p, _n) \
703     if (_n > max_) {						\
704 	if (max_ == 0) {						\
705 	    ptr_ = (debris_t *)malloc(n * sizeof(*ptr_));		\
706 	} else {						\
707 	    ptr_ = (debris_t *)realloc(ptr_, _n * sizeof(*ptr_));	\
708 	}							\
709 	if (ptr_ == NULL) {					\
710 	    error("No memory for debris");			\
711 	    num_ = max_ = 0;					\
712 	    return -1;						\
713 	}							\
714 	max_ = _n;						\
715     }								\
716     else if (_n <= 0) {						\
717 	printf("debris %d < 0\n", _n);				\
718 	return 0;						\
719     }								\
720     num_ = _n;							\
721     memcpy(ptr_, _p, _n * sizeof(*ptr_));				\
722     return 0;
723 
724 
Handle_fastshot(int type,u_byte * p,int n)725 int Handle_fastshot(int type, u_byte *p, int n)
726 {
727 #define num_		(num_fastshot[type])
728 #define max_		(max_fastshot[type])
729 #define ptr_		(fastshot_ptr[type])
730     STORE_DEBRIS(type, p, n);
731 #undef num_
732 #undef max_
733 #undef ptr_
734 }
735 
Handle_debris(int type,u_byte * p,int n)736 int Handle_debris(int type, u_byte *p, int n)
737 {
738 #define num_		(num_debris[type])
739 #define max_		(max_debris[type])
740 #define ptr_		(debris_ptr[type])
741     STORE_DEBRIS(type, p, n);
742 #undef num_
743 #undef max_
744 #undef ptr_
745 }
746 
Handle_wreckage(int x,int y,int wrecktype,int size,int rotation)747 int Handle_wreckage(int x, int y, int wrecktype, int size, int rotation)
748 {
749     wreckage_t	t;
750 
751     t.x = x;
752     t.y = y;
753     t.wrecktype = wrecktype;
754     t.size = size;
755     t.rotation = rotation;
756     STORE(wreckage_t, wreckage_ptr, num_wreckage, max_wreckage, t);
757     return 0;
758 }
759 
Handle_asteroid(int x,int y,int type,int size,int rotation)760 int Handle_asteroid(int x, int y, int type, int size, int rotation)
761 {
762     asteroid_t	t;
763 
764     t.x = x;
765     t.y = y;
766     t.type = type;
767     t.size = size;
768     t.rotation = rotation;
769     STORE(asteroid_t, asteroid_ptr, num_asteroids, max_asteroids, t);
770     return 0;
771 }
772 
Handle_wormhole(int x,int y)773 int Handle_wormhole(int x, int y)
774 {
775     wormhole_t	t;
776 
777     t.x = x - BLOCK_SZ / 2;
778     t.y = y - BLOCK_SZ / 2;
779     STORE(wormhole_t, wormhole_ptr, num_wormholes, max_wormholes, t);
780     return 0;
781 }
782 
Handle_ecm(int x,int y,int size)783 int Handle_ecm(int x, int y, int size)
784 {
785     ecm_t	t;
786 
787     t.x = x;
788     t.y = y;
789     t.size = size;
790     STORE(ecm_t, ecm_ptr, num_ecm, max_ecm, t);
791     return 0;
792 }
793 
Handle_trans(int x1,int y1,int x2,int y2)794 int Handle_trans(int x1, int y1, int x2, int y2)
795 {
796     trans_t	t;
797 
798     t.x1 = x1;
799     t.y1 = y1;
800     t.x2 = x2;
801     t.y2 = y2;
802     STORE(trans_t, trans_ptr, num_trans, max_trans, t);
803     return 0;
804 }
805 
Handle_paused(int x,int y,int count)806 int Handle_paused(int x, int y, int count)
807 {
808     paused_t	t;
809 
810     t.x = x;
811     t.y = y;
812     t.count = count;
813     STORE(paused_t, paused_ptr, num_paused, max_paused, t);
814     return 0;
815 }
816 
Handle_radar(int x,int y,int size)817 int Handle_radar(int x, int y, int size)
818 {
819     radar_t	t;
820 
821     t.x = x;
822     t.y = y;
823     t.size = size;
824     STORE(radar_t, radar_ptr, num_radar, max_radar, t);
825     return 0;
826 }
827 
Handle_message(char * msg)828 int Handle_message(char *msg)
829 {
830     Add_message(msg);
831     return 0;
832 }
833 
Handle_time_left(long sec)834 int Handle_time_left(long sec)
835 {
836     if (sec >= 0 && sec < 10 && (time_left > sec || sec == 0)) {
837 	XBell(dpy, 0);
838 	XFlush(dpy);
839     }
840     time_left = (sec >= 0) ? sec : 0;
841     return 0;
842 }
843 
Handle_vcannon(int x,int y,int type)844 int Handle_vcannon(int x, int y, int type)
845 {
846     vcannon_t	t;
847 
848     t.x = x;
849     t.y = y;
850     t.type = type;
851     STORE(vcannon_t, vcannon_ptr, num_vcannon, max_vcannon, t);
852     return 0;
853 }
854 
Handle_vfuel(int x,int y,long fuel)855 int Handle_vfuel(int x, int y, long fuel)
856 {
857     vfuel_t	t;
858 
859     t.x = x;
860     t.y = y;
861     t.fuel = fuel;
862     STORE(vfuel_t, vfuel_ptr, num_vfuel, max_vfuel, t);
863     return 0;
864 }
865 
Handle_vbase(int x,int y,int xi,int yi,int type)866 int Handle_vbase(int x, int y, int xi, int yi, int type)
867 {
868     vbase_t	t;
869 
870     t.x = x;
871     t.y = y;
872     t.xi = xi;
873     t.yi = yi;
874     t.type = type;
875     STORE(vbase_t, vbase_ptr, num_vbase, max_vbase, t);
876     return 0;
877 }
878 
Handle_vdecor(int x,int y,int xi,int yi,int type)879 int Handle_vdecor(int x, int y, int xi, int yi, int type)
880 {
881     vdecor_t	t;
882 
883     t.x = x;
884     t.y = y;
885     t.xi = xi;
886     t.yi = yi;
887     t.type = type;
888     STORE(vdecor_t, vdecor_ptr, num_vdecor, max_vdecor, t);
889     return 0;
890 }
891 
paintdataCleanup(void)892 void paintdataCleanup(void)
893 {
894     int i;
895 
896     for (i = 0; i < MAX_COLORS; i++) {
897 	if (max_rect[i] > 0 && rect_ptr[i]) {
898 	    max_rect[i] = 0;
899 	    free(rect_ptr[i]);
900 	}
901 	if (max_arc[i] > 0 && arc_ptr[i]) {
902 	    max_arc[i] = 0;
903 	    free(arc_ptr[i]);
904 	}
905 	if (max_seg[i] > 0 && seg_ptr[i]) {
906 	    max_seg[i] = 0;
907 	    free(seg_ptr[i]);
908 	}
909     }
910     if (max_refuel > 0 && refuel_ptr) {
911 	max_refuel = 0;
912 	free(refuel_ptr);
913 	refuel_ptr = 0;
914     }
915     if (max_connector > 0 && connector_ptr) {
916 	max_connector = 0;
917 	free(connector_ptr);
918 	connector_ptr = 0;
919     }
920     if (max_laser > 0 && laser_ptr) {
921 	max_laser = 0;
922 	free(laser_ptr);
923 	laser_ptr = 0;
924     }
925     if (max_missile > 0 && missile_ptr) {
926 	max_missile = 0;
927 	free(missile_ptr);
928 	missile_ptr = 0;
929     }
930     if (max_ball > 0 && ball_ptr) {
931 	max_ball = 0;
932 	free(ball_ptr);
933 	ball_ptr = 0;
934     }
935     if (max_ship > 0 && ship_ptr) {
936 	max_ship = 0;
937 	free(ship_ptr);
938 	ship_ptr = 0;
939     }
940     if (max_mine > 0 && mine_ptr) {
941 	max_mine = 0;
942 	free(mine_ptr);
943 	mine_ptr = 0;
944     }
945     if (max_ecm > 0 && ecm_ptr) {
946 	max_ecm = 0;
947 	free(ecm_ptr);
948 	ecm_ptr = 0;
949     }
950     if (max_trans > 0 && trans_ptr) {
951 	max_trans = 0;
952 	free(trans_ptr);
953 	trans_ptr = 0;
954     }
955     if (max_paused > 0 && paused_ptr) {
956 	max_paused = 0;
957 	free(paused_ptr);
958 	paused_ptr = 0;
959     }
960     if (max_radar > 0 && radar_ptr) {
961 	max_radar = 0;
962 	free(radar_ptr);
963 	radar_ptr = 0;
964     }
965     if (max_vcannon > 0 && vcannon_ptr) {
966 	max_vcannon = 0;
967 	free(vcannon_ptr);
968 	vcannon_ptr = 0;
969     }
970     if (max_vfuel > 0 && vfuel_ptr) {
971 	max_vfuel = 0;
972 	free(vfuel_ptr);
973 	vfuel_ptr = 0;
974     }
975     if (max_vbase > 0 && vbase_ptr) {
976 	max_vbase = 0;
977 	free(vbase_ptr);
978 	vbase_ptr = 0;
979     }
980     if (max_vdecor > 0 && vdecor_ptr) {
981 	max_vdecor = 0;
982 	free(vdecor_ptr);
983 	vdecor_ptr = 0;
984     }
985     if (max_itemtype > 0 && itemtype_ptr) {
986 	max_itemtype = 0;
987 	free(itemtype_ptr);
988 	itemtype_ptr = 0;
989     }
990     if (max_wreckage > 0 && wreckage_ptr) {
991 	max_wreckage = 0;
992 	free(wreckage_ptr);
993 	wreckage_ptr = 0;
994     }
995     if (max_asteroids > 0 && asteroid_ptr) {
996 	max_asteroids = 0;
997 	free(asteroid_ptr);
998 	asteroid_ptr = 0;
999     }
1000     if (max_wormholes > 0 && wormhole_ptr) {
1001 	max_wormholes = 0;
1002 	free(wormhole_ptr);
1003 	wormhole_ptr = 0;
1004     }
1005 }
1006 
1007 #ifdef	WINDOWSCALING
1008 #define SCALE_ARRAY_SIZE	32768
1009 short	scaleArray[SCALE_ARRAY_SIZE];
1010 
Init_scale_array(void)1011 void Init_scale_array(void)
1012 {
1013     int		i, start, end, n;
1014     double	scaleMultFactor;
1015 
1016     if (scaleFactor == 0.0)
1017 	scaleFactor = 1.0;
1018     if (scaleFactor < 0.1)
1019 	scaleFactor = 0.1;
1020     if (scaleFactor > 10.0)
1021 	scaleFactor = 10.0;
1022     scaleMultFactor = 1.0 / scaleFactor;
1023 
1024     scaleArray[0] = 0;
1025 
1026     for (i = 1; i < NELEM(scaleArray); i++) {
1027 	n = (int)floor(i * scaleMultFactor + 0.5);
1028 	if (n == 0) {
1029 	    /* keep values for non-zero indices at least 1. */
1030 	    scaleArray[i] = 1;
1031 	} else {
1032 	    break;
1033 	}
1034     }
1035     start = i;
1036 
1037     for (i = NELEM(scaleArray) - 1; i >= 0; i--) {
1038 	n = (int)floor(i * scaleMultFactor + 0.5);
1039 	if (n > 32767) {
1040 	    /* keep values lower or equal to max short. */
1041 	    scaleArray[i] = 32767;
1042 	} else {
1043 	    break;
1044 	}
1045     }
1046     end = i;
1047 
1048     for (i = start; i <= end; i++) {
1049 	scaleArray[i] = (int)floor(i * scaleMultFactor + 0.5);
1050     }
1051 
1052     /* verify correct calculations, because of reported gcc optimization bugs. */
1053     for (i = 1; i < NELEM(scaleArray); i++) {
1054 	if (scaleArray[i] < 1) {
1055 	    break;
1056 	}
1057     }
1058 
1059     if (i != SCALE_ARRAY_SIZE) {
1060 	fprintf(stderr,
1061 		"Error: Illegal value %d in scaleArray[%d].\n"
1062 		"\tThis error may be due to a bug in your compiler.\n"
1063 		"\tEither try a lower optimization level,\n"
1064 		"\tor a different compiler version or vendor.\n",
1065 		scaleArray[i], i);
1066 	exit(1);
1067     }
1068 }
1069 #endif
1070