1 /***********************************************************
2 * K O U L E S *
3 *----------------------------------------------------------*
4 * C1995 JAHUSOFT *
5 * Jan Hubicka *
6 * Dukelskych Bojovniku 1944 *
7 * 390 03 Tabor *
8 * Czech Republic *
9 * Phone: 0041-361-32613 *
10 * eMail: hubicka@limax.paru.cas.cz *
11 *----------------------------------------------------------*
12 * Copyright(c)1995,1996 by Jan Hubicka.See README for *
13 * licence details. *
14 *----------------------------------------------------------*
15 * koules.c main game routines *
16 ***********************************************************/
17 /* Changes for OS/2 Warp with Dive. *
18 * Copyright(c)1996 by Thomas A. K. Kjaer *
19 ***********************************************************/
20 /* Changes for joystick "accelerate by deflection" *
21 * (c) 1997 by Ludvik Tesar (Ludv\'{\i}k Tesa\v{r}) *
22 ************************LT*********************************/
23 #include <unistd.h>
24 #define VARIABLES_HERE
25 #include "koules.h"
26 #include "server.h"
27 #include "client.h"
28 #include <sys/time.h>
29 int nobjects = 8;
30 int nrockets = 0;
31 int drawpointer = 1;
32 int difficulty = 2;
33 int cit = 0;
34 #ifdef NETSUPPORT
35 int client = 0, server = 0;
36 #endif
37 Object object[MAXOBJECT];
38 Point point[MAXPOINT];
39
40
41 BitmapType bball_bitmap, apple_bitmap, inspector_bitmap, mouse_bitmap,
42 lunatic_bitmap, lball_bitmap[NLETTERS], circle_bitmap,
43 hole_bitmap, ball_bitmap, eye_bitmap[MAXROCKETS], rocket_bitmap[MAXROCKETS],
44 ehole_bitmap;
45 unsigned char rocketcolor[5] =
46 {96, 160, 64, 96, 128};
47 #ifdef SOUND
48 int sndinit = 1;
49 #endif
50
51 int lastlevel = 0, maxlevel = 0;
52 unsigned char control[MAXROCKETS];
53 struct control controls[MAXROCKETS];
54 int dosprings = 0;
55 int randsprings = 0;
56 int nomouse = 0;
57 int textcolor;
58 int sound = 1;
59 int tbreak;
60 int gameplan = COOPERATIVE;
61 int npoint = 0;
62 int gamemode;
63 int keys[5][4];
64 int rotation[MAXROCKETS];
65 int a_bballs, a_rockets, a_balls, a_holes, a_apples, a_inspectors,
66 a_lunatics, a_eholes;
67 #ifdef MOUSE
68 int mouseplayer = -1;
69 #endif
70 #ifdef JOYSTICK
71 int joystickplayer[2] =
72 {-1, -1};
73 int joystickdevice[2] =
74 {-1, -1};
75 int calibrated[2];
76 int center[2][2];
77 float joystickmul[2]={1.5,1.5};
78 float joystickthresh[2]={0.1,0.1};
79 #endif
80
81
82 float ROCKET_SPEED = 1.2;
83 float BALL_SPEED = 1.2;
84 float BBALL_SPEED = 1.2;
85 float SLOWDOWN = 0.8;
86 float GUMM = 20;
87
88
89 float BALLM = 3;
90 float LBALLM = 3;
91 float BBALLM = 8;
92 float APPLEM = 34;
93 float INSPECTORM = 2;
94 float LUNATICM = 3.14;
95 float ROCKETM = 4;
96
97
98 void
addpoint(CONST int x,CONST int y,CONST int xp,CONST int yp,CONST int color,CONST int time)99 addpoint (CONST int x, CONST int y, CONST int xp, CONST int yp, CONST int color, CONST int time)
100 {
101 point[npoint].x = x / DIV;
102 point[npoint].y = y / DIV;
103 point[npoint].xp = xp / DIV;
104 point[npoint].yp = yp / DIV;
105 point[npoint].time = time;
106
107 point[npoint].color = color;
108 npoint++;
109 if (npoint >= MAXPOINT)
110 npoint = 0;
111 }
112 #ifdef XSUPPORT /*fast code for slow X :) */
113 #define CCONST 3
114 #define PCONST 0
115 XPoint mypixels[256 >> CCONST][MAXPOINT];
116 int nmypixels[256 >> CCONST];
117 #ifdef MITSHM
118 void
shmpoints()119 shmpoints ()
120 {
121 register unsigned int x, y;
122 Point *p, *lp;
123 lp = &point[MAXPOINT];
124 for (p = point; p < lp; p++)
125 {
126 if (p->time > 0)
127 {
128 p->time--;
129 x = (p->x += p->xp) >> 8;
130 y = (p->y += p->yp);
131 if (x > 0 && x < MAPWIDTH &&
132 y > 0 && y >> 8 < MAPHEIGHT)
133 SMySetPixel (backscreen, x, y, p->color);
134 else
135 p->time = 0;
136 }
137 }
138 }
139 #endif
140 void
points()141 points ()
142 {
143 register unsigned int x, y, c;
144 Point *p, *lp;
145 #ifdef MITSHM
146 if (shm)
147 {
148 shmpoints ();
149 return;
150 }
151 #endif
152 for (x = 0; x < 256 >> CCONST; x++)
153 nmypixels[x] = 0;
154 lp = &point[MAXPOINT];
155 for (p = point; p < lp; p++)
156 {
157 if (p->time > 0)
158 {
159 p->time--;
160 x = (p->x += p->xp) >> 8;
161 y = (p->y += p->yp) >> 8;
162 if (x > 0 && x < MAPWIDTH &&
163 y > 0 && y < MAPHEIGHT)
164 {
165 c = p->color >> CCONST;
166 mypixels[c][nmypixels[c]].x = x;
167 mypixels[c][nmypixels[c]].y = y;
168 nmypixels[c]++;
169 }
170 else
171 p->time = 0;
172 }
173 }
174 for (x = 0; x < 256 >> CCONST; x++)
175 {
176 if (nmypixels[x])
177 {
178 SetColor ((x << CCONST) + PCONST);
179 XDrawPoints (dp, current.pixmap, gc, mypixels[x], nmypixels[x], CoordModeOrigin);
180 }
181 }
182 }
183 #else
184 void
points()185 points ()
186 {
187 register unsigned int x, y;
188 Point *p, *lp;
189 lp = &point[MAXPOINT];
190 for (p = point; p < lp; p++)
191 {
192 if (p->time > 0)
193 {
194 p->time--;
195 x = (p->x += p->xp) >> 8;
196 y = (p->y += p->yp);
197 if (x > 0 && x < MAPWIDTH &&
198 y > 0 && y >> 8 < MAPHEIGHT)
199 SMySetPixel (backscreen, x, y, p->color);
200 else
201 p->time = 0;
202 }
203 }
204 }
205 #endif
206
207 void
points1()208 points1 ()
209 {
210 Point *p, *lp;
211 lp = &point[MAXPOINT];
212 for (p = point; p < lp; p++)
213 {
214 if (p->time > 0)
215 {
216 p->time--;
217 p->x += p->xp;
218 p->y += p->yp;
219 }
220 }
221 }
222
223 INLINE int
radius(CONST int type)224 radius (CONST int type)
225 {
226 switch (type)
227 {
228 case EHOLE:
229 case HOLE:
230 return (HOLE_RADIUS);
231 case ROCKET:
232 return (ROCKET_RADIUS);
233 case BALL:
234 case LBALL:
235 return (BALL_RADIUS);
236 case BBALL:
237 return (BBALL_RADIUS);
238 case APPLE:
239 return (APPLE_RADIUS);
240 case INSPECTOR:
241 return (INSPECTOR_RADIUS);
242 case LUNATIC:
243 return (LUNATIC_RADIUS);
244 }
245 return (0);
246 }
247 static INLINE int
color(CONST int type,CONST int i,CONST int letter)248 color (CONST int type, CONST int i, CONST int letter)
249 {
250 switch (type)
251 {
252 case EHOLE:
253 return (128);
254 case HOLE:
255 return (64);
256 case ROCKET:
257 return (rocketcolor[i]);
258 case BALL:
259 return (64);
260 case LBALL:
261 switch (letter)
262 {
263 case L_ACCEL:
264 return (128);
265 case L_GUMM:
266 return (160);
267 case L_THIEF:
268 return (192);
269 case L_FINDER:
270 return (3 * 32);
271 case L_TTOOL:
272 return (3 * 32);
273 }
274
275 case BBALL:
276 return (128);
277 case APPLE:
278 return (64);
279 case INSPECTOR:
280 return (160);
281 case LUNATIC:
282 return (3 * 32);
283 }
284 return (0);
285 }
286 INLINE float
M(CONST int type)287 M (CONST int type)
288 {
289 switch (type)
290 {
291 case APPLE:
292 return (APPLEM);
293 case INSPECTOR:
294 return (INSPECTORM);
295 case LUNATIC:
296 return (LUNATICM);
297 case HOLE:
298 case EHOLE:
299 return (BBALLM);
300 case ROCKET:
301 return (ROCKETM);
302 case BALL:
303 case LBALL:
304 return (BALLM);
305 case BBALL:
306 return (BBALLM);
307 }
308 return (0);
309 }
310
311 int
find_possition(float * x,float * y,CONST float radius)312 find_possition (float *x, float *y, CONST float radius)
313 {
314 int x1, y1, i, y2 = 0;
315 float xp, yp;
316 rerand:;
317 x1 = rand () % (GAMEWIDTH - 60) + 30;
318 y1 = rand () % (GAMEHEIGHT - 60) + 30;
319 for (i = 0; i < nobjects; i++)
320 {
321 xp = x1 - object[i].x;
322 yp = y1 - object[i].y;
323 if (xp * xp + yp * yp < (radius + object[i].radius) *
324 (radius + object[i].radius))
325 {
326 y2++;
327 if (y2 > 10000)
328 return (0);
329 goto rerand;
330
331 }
332 }
333 *x = (float) x1;
334 *y = (float) y1;
335 return (1);
336 }
337
338 INLINE void
normalize(float * x,float * y,float size)339 normalize (float *x, float *y, float size)
340 {
341 float length = sqrt ((*x) * (*x) + (*y) * (*y));
342 if (length == 0)
343 length = 1;
344 *x *= size / length;
345 *y *= size / length;
346 }
347
348
349 static void
move_objects()350 move_objects ()
351 {
352 int i;
353 for (i = 0; i < nobjects; i++)
354 if (object[i].type == CREATOR)
355 {
356 object[i].time--;
357 if (object[i].time <= 0)
358 {
359 Effect (S_CREATOR2, next);
360 object[i].live = object[i].live1;
361 object[i].type = object[i].ctype;
362 if (object[i].type == ROCKET)
363 object[i].time = 200;
364 object[i].radius = radius (object[i].ctype);
365 object[i].M = M (object[i].ctype);
366 }
367 }
368 else if (object[i].live)
369 {
370 object[i].x += object[i].fx * (GAMEWIDTH / 640.0 + 1) / 2;
371 object[i].y += object[i].fy * (GAMEWIDTH / 640.0 + 1) / 2;
372 }
373 }
374
375
376
377
378
379 static int helpmode;
help(int x,int y,int radius,char * text)380 static void help(int x,int y,int radius,char *text)
381 {
382 int x1=x+radius+2,y1=y-4*DIV,x2=x1+strlen(text)*8*DIV,y2=y1+8*DIV;
383 if(helpmode&&x1>0&&x2<=GAMEWIDTH-DIV&&y1>0&&y2<GAMEHEIGHT-DIV) {
384 DrawBlackMaskedText(x1/DIV+1,y1/DIV+1,text);
385 DrawWhiteMaskedText(x1/DIV,y1/DIV,text);
386 }
387 }
388 char str[2];
389 static void
draw_objects(CONST int draw)390 draw_objects (CONST int draw)
391 {
392 char s[80];
393 int i;
394 if (draw)
395 {
396 CopyVSToVS (background, backscreen);
397 SetScreen (backscreen);
398
399 /* Now draw the objects in backscreen. */
400
401 points ();
402 help(0,9,0,"Help - press 'H' to disable");
403 #ifdef XSUPPORT
404 #ifdef MITSHM
405 if (!shm)
406 #else
407 if (1)
408 #endif
409 {
410 XSegment lines[MAXOBJECT];
411 int nlines = 0;
412 for (i = 0; i < nobjects; i++)
413 if (object[i].live && object[i].lineto != -1 && object[object[i].lineto].live)
414 {
415 lines[nlines].x1 = object[i].x / DIV;
416 lines[nlines].y1 = object[i].y / DIV;
417 lines[nlines].x2 = object[object[i].lineto].x / DIV;
418 lines[nlines].y2 = object[object[i].lineto].y / DIV;
419 nlines++;
420 }
421 SetColor (255);
422 XDrawSegments (dp, current.pixmap, gc, lines, nlines);
423
424 }
425 else
426 #endif
427 for (i = 0; i < nobjects; i++)
428 if (object[i].live && object[i].lineto != -1 && object[object[i].lineto].live) {
429 Line (object[i].x / DIV,
430 object[i].y / DIV,
431 object[object[i].lineto].x / DIV,
432 object[object[i].lineto].y / DIV,
433 255);
434 help((object[i].x+object[object[i].lineto].x)/2,
435 (object[i].y+object[object[i].lineto].y)/2,
436 2,"Spit");
437 }
438 for (i = 0; i < nobjects; i++)
439 if (object[i].live)
440 {
441
442 switch (object[i].type)
443 {
444 case BALL:
445 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
446 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, ball_bitmap);
447 help(object[i].x,object[i].y,object[i].radius,"Koules");
448 break;
449 case LBALL:
450 switch (object[i].letter)
451 {
452 case L_ACCEL:
453 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
454 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, lball_bitmap[0]);
455 help(object[i].x,object[i].y,object[i].radius,"Acceleration");
456 break;
457 case L_GUMM:
458 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
459 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, lball_bitmap[1]);
460 help(object[i].x,object[i].y,object[i].radius,"Weight");
461 break;
462 case L_THIEF:
463 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
464 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, lball_bitmap[2]);
465 help(object[i].x,object[i].y,object[i].radius,"Thief");
466 break;
467 case L_FINDER:
468 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
469 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, lball_bitmap[3]);
470 help(object[i].x,object[i].y,object[i].radius,"Goodie");
471 break;
472 case L_TTOOL:
473 PutBitmap ((int) (object[i].x - BALL_RADIUS) / DIV, (int) (object[i].y - BALL_RADIUS) / DIV,
474 BALL_RADIUS * 2 / DIV, BALL_RADIUS * 2 / DIV, lball_bitmap[4]);
475 help(object[i].x,object[i].y,object[i].radius,"Thief toolkit");
476 break;
477 }
478 #if !defined(XSUPPORT)||defined(MITSHM)
479 #ifdef MITSHM
480 if (DIV == 1 && shm)
481 #else
482 if (DIV == 1)
483 #endif
484 {
485 str[0] = object[i].letter;
486 DrawBlackMaskedText ((int) object[i].x / DIV - 4, (int) object[i].y / DIV - 4, str);
487 }
488 #endif
489 break;
490 case HOLE:
491 EnableClipping ();
492 PutBitmap ((int) (object[i].x - HOLE_RADIUS) / DIV, (int) (object[i].y - HOLE_RADIUS) / DIV,
493 HOLE_RADIUS * 2, HOLE_RADIUS * 2, hole_bitmap);
494 DisableClipping ();
495 help(object[i].x,object[i].y,object[i].radius,"Black hole");
496 break;
497 case EHOLE:
498 EnableClipping ();
499 PutBitmap ((int) (object[i].x - HOLE_RADIUS) / DIV, (int) (object[i].y - HOLE_RADIUS) / DIV,
500 HOLE_RADIUS * 2, HOLE_RADIUS * 2, ehole_bitmap);
501 DisableClipping ();
502 help(object[i].x,object[i].y,object[i].radius,"Magnetic hole");
503 break;
504 case BBALL:
505 PutBitmap ((int) (object[i].x - BBALL_RADIUS) / DIV, (int) (object[i].y - BBALL_RADIUS) / DIV,
506 BBALL_RADIUS * 2 / DIV, BBALL_RADIUS * 2 / DIV, bball_bitmap);
507 help(object[i].x,object[i].y,object[i].radius,"BBALL!");
508 break;
509 case INSPECTOR:
510 PutBitmap ((int) (object[i].x - INSPECTOR_RADIUS) / DIV, (int) (object[i].y - INSPECTOR_RADIUS) / DIV,
511 INSPECTOR_RADIUS * 2 / DIV, INSPECTOR_RADIUS * 2 / DIV, inspector_bitmap);
512 help(object[i].x,object[i].y,object[i].radius,"Inspector");
513 break;
514 case LUNATIC:
515 PutBitmap ((int) (object[i].x - LUNATIC_RADIUS) / DIV, (int) (object[i].y - LUNATIC_RADIUS) / DIV,
516 LUNATIC_RADIUS * 2 / DIV, LUNATIC_RADIUS * 2 / DIV, lunatic_bitmap);
517 help(object[i].x,object[i].y,object[i].radius,"Lunatic");
518 break;
519 case APPLE:
520 PutBitmap ((int) (object[i].x - APPLE_RADIUS) / DIV, (int) (object[i].y - APPLE_RADIUS) / DIV,
521 APPLE_RADIUS * 2 / DIV, APPLE_RADIUS * 2 / DIV, apple_bitmap);
522 EnableClipping ();
523 Line ((int) (object[i].x + 10) / DIV, (int) (object[i].y - APPLE_RADIUS - 10) / DIV,
524 (int) (object[i].x) / DIV, (int) (object[i].y - APPLE_RADIUS + 10) / DIV, 150);
525 Line ((int) (object[i].x + 10) / DIV + 1, (int) (object[i].y - APPLE_RADIUS - 10) / DIV,
526 (int) (object[i].x) / DIV + 1, (int) (object[i].y - APPLE_RADIUS + 10) / DIV, 150);
527 if (DIV == 1)
528 Line ((int) (object[i].x + 10) / DIV + 2, (int) (object[i].y - APPLE_RADIUS - 10) / DIV,
529 (int) (object[i].x) / DIV + 2, (int) (object[i].y - APPLE_RADIUS + 10) / DIV, 150);
530 DisableClipping ();
531 PutBitmap ((int) (object[i].x - EYE_RADIUS) / DIV,
532 (int) (object[i].y + APPLE_RADIUS - 15) / DIV,
533 EYE_RADIUS * 2 / DIV, EYE_RADIUS * 2 / DIV, eye_bitmap[0]);
534 help(object[i].x,object[i].y,object[i].radius,"APPLEPOLISHER");
535 break;
536 case ROCKET:
537 {
538 int x1, y1;
539 help(object[i].x,object[i].y,object[i].radius,"Player");
540 PutBitmap ((int) (object[i].x - ROCKET_RADIUS) / DIV, (int) (object[i].y - ROCKET_RADIUS) / DIV,
541 ROCKET_RADIUS * 2 / DIV, ROCKET_RADIUS * 2 / DIV, rocket_bitmap[i]);
542 EnableClipping ();
543 if (!object[i].thief)
544 {
545 x1 = object[i].x + sin (object[i].rotation - RAD (30)) * EYE_RADIUS1 - EYE_RADIUS;
546 y1 = object[i].y + cos (object[i].rotation - RAD (30)) * EYE_RADIUS1 - EYE_RADIUS;
547 PutBitmap ((int) (x1 / DIV), (int) (y1 / DIV),
548 (int) (EYE_RADIUS * 2 / DIV), (EYE_RADIUS * 2 / DIV), eye_bitmap[i]);
549 x1 = object[i].x + sin (object[i].rotation + RAD (30)) * EYE_RADIUS1 - EYE_RADIUS;
550 y1 = object[i].y + cos (object[i].rotation + RAD (30)) * EYE_RADIUS1 - EYE_RADIUS;
551 PutBitmap ((int) (x1 / DIV), (int) (y1 / DIV),
552 (int) (EYE_RADIUS * 2 / DIV), (EYE_RADIUS * 2 / DIV), eye_bitmap[i]);
553 }
554 else
555 {
556 x1 = object[i].x + sin (object[i].rotation - RAD (30)) * EYE_RADIUS1 - BALL_RADIUS;
557 y1 = object[i].y + cos (object[i].rotation - RAD (30)) * EYE_RADIUS1 - BALL_RADIUS;
558
559 PutBitmap ((int) (x1 / DIV), (int) (y1 / DIV),
560 (int) (BALL_RADIUS * 2 / DIV), (BALL_RADIUS * 2 / DIV), lball_bitmap[2]);
561 x1 = object[i].x + sin (object[i].rotation + RAD (30)) * EYE_RADIUS1 - BALL_RADIUS;
562 y1 = object[i].y + cos (object[i].rotation + RAD (30)) * EYE_RADIUS1 - BALL_RADIUS;
563 PutBitmap ((int) (x1 / DIV), (int) (y1 / DIV),
564 (int) (BALL_RADIUS * 2 / DIV), (BALL_RADIUS * 2 / DIV), lball_bitmap[2]);
565 }
566 DisableClipping ();
567 }
568 break;
569 }
570 }
571 }
572 /*if draw */
573 else
574 points1 ();
575 switch (gamemode)
576 {
577 case MENU:
578 draw_menu (draw);
579 break;
580 case KEYS:
581 draw_keys (draw);
582 break;
583 #ifdef JOYSTICK
584 case JOY:
585 draw_joy (draw);
586 break;
587 #endif
588 }
589
590 #ifdef MOUSE
591 if (draw && (gamemode == MENU || (gamemode == GAME && mouseplayer != -1)) &&
592 MouseX () >= 0 && MouseY () >= 0 && MouseX () < MAPWIDTH &&
593 MouseY () < MAPHEIGHT && drawpointer)
594 {
595 EnableClipping ();
596 if (!nomouse)
597 {
598 PutBitmap (MouseX () - MOUSE_RADIUS, MouseY () - MOUSE_RADIUS,
599 MOUSE_RADIUS * 2, MOUSE_RADIUS * 2, mouse_bitmap);
600 DisableClipping ();
601 }
602 }
603 #endif
604 if (draw)
605 {
606 EnableClipping ();
607 if (gameplan == COOPERATIVE && gamemode == GAME && DIV == 1)
608 {
609 sprintf (s, "level: %3i", lastlevel + 1);
610 DrawWhiteMaskedText ((MAPWIDTH / 2 - 38 * 4) / 2 - strlen (s) * 4, MAPHEIGHT + 2, s);
611 }
612 sprintf (s, " lives: %6i%6i%6i%6i%6i",
613 nrockets >= 1 ? object[0].live1 : 0,
614 nrockets >= 2 ? object[1].live1 : 0,
615 nrockets >= 3 ? object[2].live1 : 0,
616 nrockets >= 4 ? object[3].live1 : 0,
617 nrockets >= 5 ? object[4].live1 : 0);
618 DrawWhiteMaskedText (MAPWIDTH / 2 - strlen (s) * 4, MAPHEIGHT + 2, s);
619 sprintf (s, "scores: %6i%6i%6i%6i%6i",
620 object[0].score,
621 object[1].score,
622 object[2].score,
623 object[3].score,
624 object[4].score);
625 DrawWhiteMaskedText (MAPWIDTH / 2 - strlen (s) * 4, MAPHEIGHT + 11, s);
626
627 /* Copy backscreen to physical screen. */
628 CopyToScreen (backscreen);
629 fadein ();
630 DisableClipping ();
631 }
632 }
633
634
635
636
637 void
explosion(CONST int x,CONST int y,CONST int type,CONST int letter,CONST int n)638 explosion (CONST int x, CONST int y, CONST int type, CONST int letter, CONST int n)
639 {
640 float i;
641 int speed;
642 int color1;
643 int radius1 = radius (type);
644 #ifdef NETSUPPORT
645 if (server)
646 {
647 Explosion (x, y, type, letter, n);
648 return;
649 }
650 #endif
651 for (i = 0; i < RAD (360); i += RAD (360.0) * DIV * DIV / radius1 / radius1 / M_PI)
652 {
653 speed = rand () % 3096 + 10;
654 if (DIV == 1)
655 color1 = color (type, n, letter) + (rand () % 16);
656 else
657 color1 = color (type, n, letter) + (rand () % 32);
658 addpoint (x * 256, y * 256,
659 sin (i) * (speed),
660 cos (i) * (speed),
661 color1,
662 rand () % 100 + 10);
663 }
664 }
665
666
667
668 static void
rocket_destroyed(CONST int player)669 rocket_destroyed (CONST int player)
670 {
671 int i, nalive = 0, igagnant = 0;
672 if (gamemode == GAME)
673 switch (gameplan)
674 {
675 case DEATHMATCH:
676 if (nrockets == 1)
677 return;
678 for (i = 0; i < nrockets; i++)
679 if (object[i].type == ROCKET && object[i].live && i != player)
680 {
681 object[i].score += 100;
682 nalive++;
683 igagnant = i;
684 }
685 if (nalive == 1) /* winner bonus */
686 object[igagnant].score += 50;
687 }
688 }
689
690
691
692 void
destroy(CONST int i)693 destroy (CONST int i)
694 {
695 int y;
696 if (object[i].x - object[i].radius < 0)
697 object[i].x = object[i].radius + 1, object[i].fx *= -1;
698 if (object[i].y - object[i].radius < 0)
699 object[i].y = object[i].radius + 1, object[i].fy *= -1;
700 if (object[i].x + object[i].radius > GAMEWIDTH)
701 object[i].x = GAMEWIDTH - object[i].radius - 1, object[i].fx *= -1;
702 if (object[i].y + object[i].radius > GAMEHEIGHT)
703 object[i].y = GAMEHEIGHT - object[i].radius - 1, object[i].fy *= -1;
704 switch (object[i].type)
705 {
706 case LBALL:
707 Effect (S_DESTROY_BALL, next);
708 object[i].live = 0, explosion (object[i].x, object[i].y, object[i].type, object[i].letter, i);
709 if (object[i].letter == L_THIEF && allow_finder ())
710 {
711 object[i].live = 1;
712 object[i].letter = L_FINDER;
713 } /* else
714 if (object[i].letter == L_FINDER )
715 {
716 object[i].live = 1;
717 object[i].letter = L_THIEF;
718 } */
719 break;
720 case APPLE:
721 Effect (S_DESTROY_ROCKET, 0);
722 object[i].live = 0, explosion (object[i].x, object[i].y, object[i].type, object[i].letter, i);
723 break;
724 case BALL:
725 case EHOLE:
726 case BBALL:
727 case INSPECTOR:
728 case LUNATIC:
729 Effect (S_DESTROY_BALL, next);
730 if ((y = create_letter ()) != 0)
731 {
732 object[i].type = LBALL;
733 object[i].M = LBALLM;
734 switch (y)
735 {
736 case 1:
737 object[i].letter = L_ACCEL;
738 break;
739 case 2:
740 object[i].letter = L_GUMM;
741 break;
742 case 3:
743 object[i].letter = L_THIEF;
744 break;
745 case 4:
746 object[i].letter = L_FINDER;
747 break;
748 case 5:
749 object[i].letter = L_TTOOL;
750 break;
751 /*case 3:
752 object[i].letter = L_MUGG;
753 break;
754 case 4:
755 object[i].letter = L_SLOW;
756 break;
757 case 5:
758 object[i].letter = L_WIZZ;
759 break;
760 case 6:
761 object[i].letter = L_FUCK;
762 break; */
763 }
764 }
765 else
766 object[i].live = 0, explosion (object[i].x, object[i].y, object[i].type, object[i].letter, i);
767 break;
768 case ROCKET:
769 Effect (S_DESTROY_ROCKET, 0);
770 object[i].live1--, object[i].live--, explosion (object[i].x, object[i].y, object[i].type, object[i].letter, i);
771 rocket_destroyed (i);
772 if (object[i].live)
773 {
774 /*object[i].x = rand () % (GAMEWIDTH-60)+30;
775 object[i].y = rand () % (GAMEHEIGHT-60)+30; */
776 object[i].fx = 0;
777 object[i].fy = 0;
778 object[i].rotation = 0;
779 object[i].type = ROCKET;
780 object[i].accel = ROCKET_SPEED;
781 creator_rocket (i);
782 }
783 break;
784 }
785 }
786
787
788
789
790 static void
check_limit()791 check_limit ()
792 {
793 int i;
794 for (i = 0; i < nobjects; i++)
795 if (object[i].live)
796 {
797 if (object[i].x - object[i].radius < 0 || object[i].x + object[i].radius >= GAMEWIDTH ||
798 object[i].y - object[i].radius <= 0 || object[i].y + object[i].radius >= GAMEHEIGHT)
799 {
800 destroy (i);
801 }
802 }
803 }
804
805
806
807 /*
808 * count number of creatures
809 */
810 static void
update_values()811 update_values ()
812 {
813 int i;
814 a_holes = 0;
815 a_rockets = 0;
816 a_balls = 0;
817 a_bballs = 0;
818 a_apples = 0;
819 a_eholes = 0;
820 a_inspectors = 0;
821 a_lunatics = 0;
822 for (i = 0; i < nobjects; i++)
823 {
824 if (object[i].live)
825 {
826 switch (object[i].type)
827 {
828 case HOLE:
829 a_holes++;
830 break;
831 case EHOLE:
832 a_eholes++;
833 break;
834 case ROCKET:
835 a_rockets++;
836 break;
837 case LBALL:
838 case BALL:
839 a_balls++;
840 break;
841 case BBALL:
842 a_bballs++;
843 break;
844 case APPLE:
845 a_apples++;
846 break;
847 case INSPECTOR:
848 a_inspectors++;
849 break;
850 case LUNATIC:
851 a_lunatics++;
852 break;
853 }
854 }
855 if (object[i].type == CREATOR)
856 {
857 switch (object[i].ctype)
858 {
859 case BBALL:
860 a_bballs++;
861 break;
862 case HOLE:
863 a_holes++;
864 break;
865 case EHOLE:
866 a_eholes++;
867 break;
868 case ROCKET:
869 a_rockets++;
870 break;
871 case LBALL:
872 case BALL:
873 a_balls++;
874 break;
875 case APPLE:
876 a_apples++;
877 break;
878 case INSPECTOR:
879 a_inspectors++;
880 break;
881 case LUNATIC:
882 a_lunatics++;
883 break;
884 }
885 }
886 }
887
888 }
889
890
891
892 /*
893 * accelerate rocket
894 */
895 void
896 /* howmuch is between 0 and 1, everything else is cheating */
accel(CONST int i,CONST double howmuch)897 accel (CONST int i, CONST double howmuch)
898 {
899 int y;
900 #ifdef NETSUPPORT
901 if (server)
902 acceled[i] = 1;
903 #endif
904 #ifdef NETSUPPORT
905 if (!client)
906 #endif
907 {
908 object[i].time = 0;
909 object[i].fx += howmuch * sin (object[i].rotation) * object[i].accel,
910 object[i].fy += howmuch * cos (object[i].rotation) * object[i].accel;
911 #ifdef NETSUPPORT
912 if (!server)
913 #endif
914 for (y = 0; y < 5 / DIV / DIV; y++)
915 {
916 float p;
917 p = RAD (rand () % 45 - 22);
918 addpoint (object[i].x * 256,
919 object[i].y * 256,
920 (object[i].fx - howmuch * sin (object[i].rotation + p) * object[i].accel * 10) * (rand () % 512),
921 (object[i].fy - howmuch * cos (object[i].rotation + p) * object[i].accel * 10) * (rand () % 512),
922 rocket (rand () % 16), 10);
923 }
924 }
925 #ifdef NETSUPPORT
926 else
927 {
928 for (y = 0; y < 5 / DIV / DIV; y++)
929 {
930 float p;
931 p = RAD (rand () % 30 - 15);
932 addpoint (object[i].x * 256,
933 object[i].y * 256,
934 (-sin (object[i].rotation + p) * ROCKET_SPEED * 5) * (rand () % 512),
935 (-cos (object[i].rotation + p) * ROCKET_SPEED * 5) * (rand () % 512),
936 rocket (rand () % 16), 10);
937 }
938 }
939 #endif
940 }
941
942
943 static void
sprocess_keys()944 sprocess_keys ()
945 {
946 int i;
947 if (gamemode != GAME)
948 return;
949 for (i = 0; i < MAXROCKETS; i++)
950 {
951 if (object[i].live && object[i].type == ROCKET)
952 {
953 switch (controls[i].type)
954 {
955 #ifdef JOYSTICK
956 case C_JOYSTICK1:
957 {
958 double a, x = controls[i].jx, y = controls[i].jy;
959 a = atan (fabs (y) / fabs (x));
960 if (x < 0 && y >= 0)
961 object[i].rotation = a + RAD (90);
962 else if (x < 0 && y < 0)
963 object[i].rotation = RAD (90) - a;
964 else if (x >= 0 && y < 0)
965 object[i].rotation = a + RAD (270);
966 else if (x >= 0 && y >= 0)
967 object[i].rotation = RAD (270) - a;
968 /* Measure the deflection (a is betw. 0 and 1) */
969 a=hypot(x*object[i].joymulx,y*object[i].joymuly);
970 /* I must make sure, that I am not cheating :-) */
971 /* "a" can't be bigger than one */
972 if((a>1.0)||(controls[i].mask!=0))a=1.0;
973 if(a>object[i].joythresh)accel(i,a);
974 }
975 break;
976 #endif
977 case C_MOUSE:
978 {
979 double dx, dy, a;
980 dx = object[i].x - controls[i].mx;
981 dy = object[i].y - controls[i].my;
982 if (dx == 0)
983 dx = 0.001;
984 a = atan (fabs (dy) / fabs (dx));
985 if (dx < 0 && dy >= 0)
986 object[i].rotation = a + RAD (90);
987 else if (dx < 0 && dy < 0)
988 object[i].rotation = RAD (90) - a;
989 else if (dx >= 0 && dy < 0)
990 object[i].rotation = a + RAD (270);
991 else if (dx >= 0 && dy >= 0)
992 object[i].rotation = RAD (270) - a;
993 if (controls[i].mask)
994 accel (i ,1.0);
995 }
996 break;
997 case C_RKEYBOARD:
998 if (controls[i].mask & 1)
999 object[i].rotation += ROTSTEP;
1000 if (controls[i].mask & 2)
1001 object[i].rotation -= ROTSTEP;
1002 if (controls[i].mask & 4)
1003 accel (i ,1.0);
1004 break;
1005 case C_KEYBOARD:
1006 switch (controls[i].mask)
1007 {
1008 case 1:
1009 object[i].rotation = RAD (-135), accel (i ,1.0);
1010 break;
1011 case 2:
1012 object[i].rotation = RAD (135), accel (i ,1.0);
1013 break;
1014 case 3:
1015 object[i].rotation = RAD (45), accel (i ,1.0);
1016 break;
1017 case 4:
1018 object[i].rotation = RAD (-45), accel (i ,1.0);
1019 break;
1020 case 5:
1021 object[i].rotation = RAD (-90), accel (i ,1.0);
1022 break;
1023 case 6:
1024 object[i].rotation = RAD (90), accel (i ,1.0);
1025 break;
1026 case 7:
1027 object[i].rotation = RAD (180), accel (i ,1.0);
1028 break;
1029 case 8:
1030 object[i].rotation = RAD (0), accel (i ,1.0);
1031 break;
1032 }
1033
1034 }
1035 }
1036 }
1037 }
1038
1039 void
process_keys()1040 process_keys ()
1041 {
1042 int i;
1043 static int lasth=0;
1044 #ifdef JOYSTICK
1045 int status;
1046 struct JS_DATA_TYPE js;
1047 #endif
1048
1049
1050 UpdateInput ();
1051 if (IsPressedH () && !lasth)
1052 {
1053 helpmode^=1;
1054 }
1055 lasth=IsPressedH();
1056 if (IsPressedP () && !client)
1057 {
1058 int k = 1;
1059 SetScreen (backscreen);
1060 DrawText (MAPWIDTH / 2 - 20, MAPHEIGHT / 2 - 4, "PAUSE");
1061 CopyToScreen(backscreen);
1062 #ifdef OS2DIVE
1063 forceBlitting ();
1064 #endif
1065 tbreak = 1;
1066 while (k)
1067 {
1068 UpdateInput ();
1069 k = Pressed ();
1070 #ifdef OS2DIVE
1071 DosSleep (WAIT);
1072 #endif
1073 }
1074 while (!k)
1075 {
1076 UpdateInput ();
1077 k = Pressed ();
1078 #ifdef OS2DIVE
1079 DosSleep (WAIT);
1080 #endif
1081 }
1082 }
1083 switch (gamemode)
1084 {
1085 case MENU:
1086 menu_keys ();
1087 break;
1088 case KEYS:
1089 keys_keys ();
1090 break;
1091 #ifdef JOYSTICK
1092 case JOY:
1093 joy_keys ();
1094 break;
1095 #endif
1096 case GAME:
1097 #ifdef JOYSTICK
1098 for (i = 0; i < 2; i++)
1099 {
1100 double x, y;
1101 if (joystickplayer[i] >= 0)
1102 {
1103 if (object[joystickplayer[i]].type != ROCKET)
1104 continue;
1105 status = read (joystickdevice[i], &js, JS_RETURN);
1106 if (status != JS_RETURN)
1107 {
1108 break;
1109 }
1110 x = center[i][0] - js.x;
1111 y = center[i][1] - js.y;
1112 if (x == 0)
1113 x = 0.001;
1114 controls[joystickplayer[i]].jx = x;
1115 controls[joystickplayer[i]].jy = y;
1116 controls[joystickplayer[i]].mask = js.buttons;
1117 controls[joystickplayer[i]].type = C_JOYSTICK1;
1118
1119 }
1120 }
1121 #endif
1122 #ifdef MOUSE
1123 /* Move. */
1124 if (mouseplayer != -1 && object[mouseplayer].type == ROCKET
1125 /*&& (MouseButtons ()||controls[mouseplayer].mask) */ )
1126 {
1127 controls[mouseplayer].mx = MouseX () * DIV;
1128 controls[mouseplayer].my = MouseY () * DIV;
1129 controls[mouseplayer].mask = MouseButtons () != 0;
1130 controls[mouseplayer].type = C_MOUSE;
1131 }
1132 #endif
1133 if (IsPressedEsc ())
1134 {
1135 #ifdef NETSUPPORT
1136 if (!client)
1137 {
1138 #endif
1139 gamemode = MENU;
1140 while (IsPressedEsc ())
1141 UpdateInput ();
1142 #ifdef NETSUPPORT
1143 }
1144 else
1145 {
1146 CQuit ("client exit-ESC pressed\n");
1147 }
1148 #endif
1149 }
1150 for (i = 0; i < nrockets; i++)
1151 {
1152 #ifdef MOUSE
1153 if (i == mouseplayer)
1154 continue;
1155 #endif
1156 #ifdef JOYSTICK
1157 if (i == joystickplayer[0] ||
1158 i == joystickplayer[1])
1159 continue;
1160 #endif
1161 #ifdef NETSUPPORT
1162 if (client && !control[i])
1163 continue;
1164 #endif
1165 if (object[i].type != ROCKET)
1166 continue;
1167 if (rotation[i])
1168 {
1169 char s = 0;
1170 if (IsPressed (keys[i][1]))
1171 s = 1;
1172 if (IsPressed (keys[i][2]))
1173 s |= 2;
1174 if (IsPressed (keys[i][0]))
1175 s |= 4;
1176 controls[i].type = C_RKEYBOARD;
1177 controls[i].mask = s;
1178 }
1179 else
1180 {
1181 int s = 0;
1182 if (IsPressed (keys[i][2]) && IsPressed (keys[i][0]))
1183 s = 1;
1184 else if (IsPressed (keys[i][3]) && IsPressed (keys[i][0]))
1185 s = 2;
1186 else if (IsPressed (keys[i][1]) && IsPressed (keys[i][3]))
1187 s = 3;
1188 else if (IsPressed (keys[i][1]) && IsPressed (keys[i][2]))
1189 s = 4;
1190 else if (IsPressed (keys[i][2]))
1191 s = 5;
1192 else if (IsPressed (keys[i][3]))
1193 s = 6;
1194 else if (IsPressed (keys[i][0]))
1195 s = 7;
1196 else if (IsPressed (keys[i][1]))
1197 s = 8;
1198 controls[i].type = C_KEYBOARD;
1199 controls[i].mask = s;
1200 }
1201 }
1202 break;
1203 }
1204
1205
1206
1207 }
1208
1209 #define MIN(a,b) ((a)>(b)?(b):(a))
1210 /*
1211 * Make creations happen as coalescing circular cloud. Do this by
1212 * creating random points within circle defined from center of screen, and
1213 * giving them velocity towards desired final point.
1214 */
1215
1216 void
creators_points(int radius,int x1,int y1,int color1)1217 creators_points (int radius, int x1, int y1, int color1)
1218 {
1219 int z, x, y, x2, y2;
1220 double r;
1221 int time = 50;
1222 int midX, midY, r2,r1;
1223
1224 midX = GAMEWIDTH / 2;
1225 midY = GAMEHEIGHT / 2;
1226 r2 = r1 = MIN(midX, midY);
1227 r2 *= r2;
1228
1229 z = radius * radius * M_PI / DIV / DIV;
1230 while (z--) {
1231 do {
1232 x = rand() % GAMEWIDTH;
1233 y = rand() % GAMEHEIGHT;
1234 } while (((x-midX)*(x-midX) + (y-midY)*(y-midY)) > r2);
1235 r=sqrt((double)((x-midX)*(x-midX) + (y-midY)*(y-midY)));
1236 r=(r*radius/r1)/r*0.9;
1237 x2=x1+(x-midX)*r;
1238 y2=y1+(y-midY)*r;
1239
1240 addpoint(x * 256, y * 256,
1241 (x2 - x) * 256 / (time),
1242 (y2 - y) * 256 / (time),
1243 color1 + (rand() % (DIV == 1 ? 16 : 32)),
1244 time);
1245 }
1246 }
1247
1248 void
creator(CONST int type)1249 creator (CONST int type)
1250 {
1251 int i;
1252 int color1 = color (type, 0, 0);
1253 for (i = nrockets; i < nobjects && (object[i].live ||
1254 object[i].type == CREATOR);
1255 i++);
1256 if (i >= MAXOBJECT)
1257 return;
1258 if (!find_possition (&object[i].x, &object[i].y, radius (type)))
1259 return;
1260 if (i >= nobjects)
1261 nobjects = i + 1;
1262 object[i].live = 0;
1263 object[i].live1 = 1;
1264 object[i].lineto = -1;
1265 object[i].ctype = type;
1266 object[i].fx = 0.0;
1267 object[i].fy = 0.0;
1268 object[i].time = 50;
1269 object[i].rotation = 0;
1270 object[i].type = CREATOR;
1271 object[i].M = M (type);
1272 object[i].radius = radius (type);
1273 object[i].accel = ROCKET_SPEED;
1274 object[i].letter = ' ';
1275 #ifdef NETSUPPORT
1276 if (server)
1277 CreatorsPoints (object[i].radius, object[i].x, object[i].y, color1);
1278 else
1279 #endif
1280 creators_points (object[i].radius, object[i].x, object[i].y, color1);
1281 Effect (S_CREATOR1, 0);
1282 }
1283
1284
1285 void
creator_rocket(CONST int i)1286 creator_rocket (CONST int i)
1287 {
1288 int type = ROCKET;
1289 int color1 = color (ROCKET, i, 0);
1290 if (!find_possition (&object[i].x, &object[i].y, radius (type)))
1291 return;
1292 if (sound)
1293 object[i].live1 = object[i].live;
1294 object[i].live = 0;
1295 object[i].thief = 0;
1296 object[i].ctype = type;
1297 object[i].lineto = -1;
1298 object[i].fx = 0.0;
1299 object[i].fy = 0.0;
1300 object[i].time = 50;
1301 object[i].rotation = 0;
1302 object[i].type = CREATOR;
1303 object[i].M = ROCKETM;
1304 object[i].radius = ROCKET_RADIUS;
1305 object[i].accel = ROCKET_SPEED;
1306 object[i].letter = ' ';
1307 #ifdef NETSUPPORT
1308 if (server)
1309 CreatorsPoints (ROCKET_RADIUS, object[i].x, object[i].y, color1);
1310 else
1311 #endif
1312 creators_points (ROCKET_RADIUS, object[i].x, object[i].y, color1);
1313 }
1314
1315
1316
1317
1318 static void
update_forces()1319 update_forces ()
1320 {
1321 int i;
1322 int r;
1323 float d;
1324 float xp, yp;
1325 int frocket = 0;
1326 for (i = 0; i < nobjects; i++)
1327 {
1328 if (object[i].live)
1329 {
1330 if (object[i].lineto != -1)
1331 {
1332 if (!object[object[i].lineto].live)
1333 object[i].lineto = -1;
1334 else if (object[i].lineto == i)
1335 object[i].lineto = -1;
1336 else
1337 {
1338 int force;
1339 xp = object[i].x - object[object[i].lineto].x;
1340 yp = object[i].y - object[object[i].lineto].y;
1341 force = sqrt (xp * xp + yp * yp);
1342 if (force >= 2 * SPRINGSIZE || gameplan == COOPERATIVE)
1343 {
1344 force = force - SPRINGSIZE;
1345 if (force < 0)
1346 force *= 3;
1347 force = force / SPRINGSTRENGTH;
1348 normalize (&xp, &yp, force * BALL_SPEED / object[i].M);
1349 object[i].fx -= xp;
1350 object[i].fy -= yp;
1351 normalize (&xp, &yp, force * BALL_SPEED / object[object[i].lineto].M);
1352 object[object[i].lineto].fx += xp;
1353 object[object[i].lineto].fy += yp;
1354 }
1355 }
1356 }
1357 if (object[i].type == ROCKET && object[i].time)
1358 object[i].time--;
1359 if (object[i].type == ROCKET && !object[i].time)
1360 {
1361 d = 640 * 640;
1362 frocket = -1;
1363 for (r = 0; r < nobjects; r++)
1364 {
1365 if (object[r].live && !object[r].time && object[r].type == EHOLE)
1366 {
1367 int distance;
1368 float gravity;
1369 xp = object[r].x - object[i].x;
1370 yp = object[r].y - object[i].y;
1371 distance = sqrt (xp * xp + yp * yp);
1372 gravity = BALL_SPEED * (gameplan == COOPERATIVE ? 200 : 50) / distance;
1373 if (gravity > BALL_SPEED * 4 / 5)
1374 gravity = BALL_SPEED * 4 / 5;
1375 normalize (&xp, &yp, gravity);
1376 object[i].fx += xp;
1377 object[i].fy += yp;
1378 }
1379 }
1380
1381 }
1382 if (object[i].type == BALL || object[i].type == LBALL || object[i].type == BBALL || object[i].type == LUNATIC)
1383 {
1384 frocket = -1;
1385 d = 640 * 640;
1386 for (r = 0; r < nrockets; r++)
1387 {
1388 if (object[r].live && !object[r].time)
1389 {
1390 xp = object[r].x - object[i].x;
1391 yp = object[r].y - object[i].y;
1392 if (xp * xp + yp * yp < d)
1393 d = xp * xp + yp * yp, frocket = r;
1394 }
1395 }
1396 if (frocket != -1)
1397 xp = object[frocket].x - object[i].x,
1398 yp = object[frocket].y - object[i].y;
1399 else
1400 xp = GAMEWIDTH / 2 - object[i].x,
1401 yp = GAMEHEIGHT / 2 - object[i].y;
1402 if (object[i].type == LUNATIC && !rand () % 4)
1403 {
1404 xp = rand ();
1405 yp = rand () + 1;
1406 }
1407 switch (object[i].type)
1408 {
1409 case BBALL:
1410 normalize (&xp, &yp, BBALL_SPEED);
1411 break;
1412 case BALL:
1413 case LUNATIC:
1414 case LBALL:
1415 normalize (&xp, &yp, BALL_SPEED);
1416 break;
1417 }
1418 object[i].fx += xp;
1419 object[i].fy += yp;
1420 }
1421 object[i].fx *= SLOWDOWN,
1422 object[i].fy *= SLOWDOWN;
1423 }
1424 }
1425 }
1426
1427
1428
1429
1430 static void
colisions()1431 colisions ()
1432 {
1433 int i, y;
1434 int colize = 0;
1435 static int ctime = 0;
1436 float xp, yp, gummfactor;
1437 for (i = 0; i < nobjects; i++)
1438 if (object[i].live)
1439 for (y = i + 1; y < nobjects; y++)
1440 if (object[y].live)
1441 {
1442 xp = object[y].x - object[i].x;
1443 yp = object[y].y - object[i].y;
1444 if (xp * xp + yp * yp < (object[y].radius + object[i].radius) *
1445 (object[y].radius + object[i].radius))
1446 {
1447 colize = 1;
1448 if (object[i].type == HOLE || object[i].type == EHOLE)
1449 {
1450 if (object[y].type != APPLE)
1451 destroy (y);
1452 if (object[i].type == EHOLE)
1453 destroy (i);
1454 continue;
1455 }
1456 if (object[y].type == HOLE || object[y].type == EHOLE)
1457 {
1458 if (object[i].type != APPLE)
1459 destroy (i);
1460 if (object[y].type == EHOLE)
1461 destroy (y);
1462 continue;
1463 }
1464 if (object[i].type == ROCKET)
1465 {
1466 if (object[y].thief == 1 && object[i].thief == 1)
1467 {
1468 float tmp;
1469 tmp = object[i].M;
1470 object[i].M = object[y].M;
1471 object[y].M = tmp;
1472 object[i].thief = 0;
1473 object[y].thief = 0;
1474 }
1475 if (object[y].type == BBALL && object[i].thief == 1)
1476 {
1477 object[i].M += object[y].M - M (BALL);
1478 object[i].thief = 0;
1479 object[y].M = M (BALL);
1480 }
1481 else if (object[y].type == ROCKET && object[i].thief == 1)
1482 {
1483 object[i].M += object[y].M - M (ROCKET);
1484 object[i].accel += object[y].accel - ROCKET_SPEED;
1485 object[i].thief = 0;
1486 object[y].M = M (object[i].type);
1487 object[y].accel = ROCKET_SPEED - A_ADD;
1488 }
1489 if (object[i].type == ROCKET && object[y].thief == 1)
1490 {
1491 object[y].M += object[i].M - M (ROCKET);
1492 object[y].accel += object[i].accel - ROCKET_SPEED;
1493 object[y].thief = 0;
1494 object[i].M = M (object[y].type);
1495 object[i].accel = ROCKET_SPEED - A_ADD;
1496 }
1497 if (gameplan == COOPERATIVE)
1498 object[i].score++;
1499 if (object[y].letter == L_ACCEL)
1500 object[i].accel += A_ADD,
1501 object[i].score += 10;
1502 if (object[y].letter == L_GUMM)
1503 object[i].M += M_ADD,
1504 object[i].score += 10;
1505 if (object[y].letter == L_THIEF)
1506 object[i].M = M (object[i].type),
1507 object[i].accel = ROCKET_SPEED - A_ADD,
1508 object[i].score -= 30;
1509 if (object[y].letter == L_FINDER)
1510 {
1511 object[i].accel += A_ADD * (rand () % 5);
1512 object[i].M += M_ADD * (rand () % 10);
1513 object[i].score += 30;
1514 }
1515 if (object[y].letter == L_TTOOL)
1516 {
1517 object[i].thief = 1;
1518 object[i].score += 30;
1519 }
1520
1521 object[y].letter = ' ';
1522 if (object[y].type == LBALL)
1523 object[y].type = BALL;
1524 if (object[y].type == BALL && dosprings && !(rand () % randsprings))
1525 object[y].lineto = i;
1526
1527 if (gameplan == DEATHMATCH && object[y].type == ROCKET && dosprings && !(rand () % (2 * randsprings)))
1528 object[y].lineto = i;
1529 }
1530 if (object[y].type == LUNATIC)
1531 {
1532 gummfactor = -ROCKETM / LUNATICM;
1533 }
1534 else if (object[i].type == LUNATIC)
1535 {
1536 gummfactor = -LUNATICM / ROCKETM;
1537 }
1538 else
1539 gummfactor = object[i].M / object[y].M;
1540 normalize (&xp, &yp, gummfactor * GUMM);
1541 object[y].fx += xp;
1542 object[y].fy += yp;
1543 normalize (&xp, &yp, 1 / gummfactor * GUMM);
1544 object[i].fx -= xp;
1545 object[i].fy -= yp;
1546 if (object[i].type == ROCKET && object[i].time)
1547 object[i].fx = 0,
1548 object[i].fy = 0;
1549 if (object[y].type == ROCKET && object[y].time)
1550 object[y].fx = 0,
1551 object[y].fy = 0;
1552 if (object[y].type == INSPECTOR && object[i].type == ROCKET)
1553 {
1554 object[y].fx = 0,
1555 object[y].fy = 0;
1556 object[i].fx *= -2,
1557 object[i].fy *= -2;
1558 }
1559 }
1560 }
1561 if (colize && !ctime)
1562 {
1563 #ifndef NAS_SOUND
1564 Effect (S_COLIZE, next);
1565 #endif
1566 ctime = 4;
1567 }
1568 if (ctime)
1569 ctime--;
1570 }
1571
1572
1573
1574 void
game()1575 game ()
1576 {
1577 long VfTime = 0;
1578 long VendSleep = 0;
1579 struct timeval VlastClk;
1580 struct timeval VnewClk;
1581 int wait = 0;
1582
1583 load_rc ();
1584 init_menu ();
1585 gettimeofday (&VlastClk, NULL);
1586 gettimeofday (&VnewClk, NULL);
1587 VendSleep = VlastClk.tv_usec;
1588 VfTime = 1000000 / 25;
1589
1590
1591 while (1)
1592 {
1593 process_keys ();
1594 sprocess_keys ();
1595 update_values ();
1596 update_game ();
1597 update_forces ();
1598 colisions ();
1599 move_objects ();
1600 check_limit ();
1601 gettimeofday (&VnewClk, NULL);
1602 if (VnewClk.tv_usec < VendSleep)
1603 VendSleep -= 1000000;
1604 wait = (VfTime - VnewClk.tv_usec + VendSleep);
1605 if (wait > 0 || tbreak)
1606 draw_objects (1);
1607 else
1608 draw_objects (0);
1609 gettimeofday (&VnewClk, NULL);
1610 if (VnewClk.tv_usec < VendSleep)
1611 VendSleep -= 1000000;
1612 wait = (VfTime - VnewClk.tv_usec + VendSleep);
1613 if (tbreak)
1614 wait = VfTime;
1615 if (wait > 0)
1616 usleep (wait);
1617 VendSleep = VnewClk.tv_usec + wait;
1618 gettimeofday (&VlastClk, NULL);
1619 if (tbreak)
1620 tbreak = 0,
1621 VendSleep = VlastClk.tv_usec;
1622
1623 }
1624 }
1625 #ifdef NETSUPPORT
1626 void
client_loop2(int draw)1627 client_loop2 (int draw) /*game part of server loop */
1628 {
1629 draw_objects (draw);
1630 switch (gamemode)
1631 {
1632 case MENU:
1633 draw_menu (draw);
1634 break;
1635 case KEYS:
1636 draw_keys (draw);
1637 break;
1638 #ifdef JOYSTICK
1639 case JOY:
1640 draw_joy (draw);
1641 break;
1642 #endif
1643 }
1644 }
1645 void
server_loop2(void)1646 server_loop2 (void) /*game part of server loop */
1647 {
1648 sprocess_keys ();
1649 update_values ();
1650 update_game ();
1651 update_forces ();
1652 colisions ();
1653 move_objects ();
1654 check_limit ();
1655 }
1656 #endif
1657