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