1 // Emacs style mode select -*- C++ -*-
2 //---------------------------------------------------------------------------
3 //
4 // $Id: swmove.c,v 1.6.2.1 2003/06/08 18:16:38 fraggle Exp $
5 //
6 // Copyright(C) 1984-2000 David L. Clark
7 // Copyright(C) 2001-2003 Simon Howard
8 //
9 // This program is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by the
11 // Free Software Foundation; either version 2 of the License, or (at your
12 // option) any later version. This program is distributed in the hope that
13 // it will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 // the GNU General Public License for more details. You should have
16 // received a copy of the GNU General Public License along with this
17 // program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 // Place - Suite 330, Boston, MA 02111-1307, USA.
19 //
20 //---------------------------------------------------------------------------
21 //
22 // swmove - SW move all objects and players
23 //
24 //---------------------------------------------------------------------------
25
26 #include "video.h"
27
28 #include "sw.h"
29 #include "swasynio.h"
30 #include "swauto.h"
31 #include "swcollsn.h"
32 #include "swdisp.h"
33 #include "swend.h"
34 #include "swground.h"
35 #include "swgrpha.h"
36 #include "swinit.h"
37 #include "swmain.h"
38 #include "swmove.h"
39 #include "swobject.h"
40 #include "swsound.h"
41 #include "swsymbol.h"
42 #include "swtitle.h"
43 #include "swutil.h"
44
45 static BOOL quit;
46
swmove()47 void swmove()
48 {
49 register OBJECTS *ob, *obn;
50
51 if (deltop) {
52 delbot->ob_next = objfree;
53 objfree = deltop;
54 deltop = delbot = NULL;
55 }
56
57 ++dispcnt;
58
59 if (dispcnt >= keydelay)
60 dispcnt = 0;
61
62 ob = objtop;
63 while (ob) {
64 obn = ob->ob_next;
65 ob->ob_delflg = ob->ob_drwflg;
66 ob->ob_oldsym = ob->ob_newsym;
67 ob->ob_drwflg = (*ob->ob_movef) (ob);
68 ob = obn;
69 }
70
71 ++countmove;
72 }
73
74
nearpln(OBJECTS * obp)75 static void nearpln(OBJECTS * obp)
76 {
77 register OBJECTS *ob, *obt, *obc;
78 register int i, obx, obclr;
79
80 ob = obp;
81 obt = objtop + 1;
82
83 obx = ob->ob_x;
84 obclr = ob->ob_owner->ob_clr;
85
86 for (i = 1; obt->ob_type == PLANE; ++i, ++obt) {
87 if (obclr == obt->ob_owner->ob_clr)
88 continue;
89
90 // sdh: removed use of "equal" function to compare
91 // function pointers (why???)
92
93 if (obt->ob_drawf == dispcomp)
94
95 if (playmode != PLAYMODE_COMPUTER
96 || (obx >= lcompter[i] && obx <= rcompter[i])) {
97 obc = compnear[i];
98 if (!obc
99 || abs(obx - obt->ob_x)
100 < abs(obc->ob_x - obt->ob_x))
101 compnear[i] = ob;
102 }
103 }
104 }
105
106
107
108
topup(int * counter,int max)109 static int topup(int *counter, int max)
110 {
111 BOOL rc;
112
113 rc = FALSE;
114 if (*counter == max)
115 return rc;
116 if (max < 20) {
117 if (!(countmove % 20)) {
118 ++*counter;
119 rc = plyrplane;
120 }
121 } else {
122 *counter += max / 100;
123 rc = plyrplane;
124 }
125 if (*counter > max)
126 *counter = max;
127 return rc;
128 }
129
130
refuel(OBJECTS * obp)131 static void refuel(OBJECTS * obp)
132 {
133 register OBJECTS *ob;
134 BOOL topped_up;
135
136 ob = obp;
137 setvdisp();
138
139 // sdh 26/10/2001: top up stuff, if anything happens update
140 // the guages (now a single function)
141 // sdh 27/10/2001: fix refueling in parallel (was a single
142 // set of ||'s and was being shortcircuited)
143
144 topped_up = topup(&ob->ob_life, MAXFUEL);
145 topped_up |= topup(&ob->ob_rounds, MAXROUNDS);
146 topped_up |= topup(&ob->ob_bombs, MAXBOMBS);
147 topped_up |= topup(&ob->ob_missiles, MAXMISSILES);
148 topped_up |= topup(&ob->ob_bursts, MAXBURSTS);
149
150 if (topped_up)
151 dispguages(ob);
152 }
153
154
155
symangle(OBJECTS * ob)156 static int symangle(OBJECTS * ob)
157 {
158 register int dx, dy;
159
160 dx = ob->ob_dx;
161 dy = ob->ob_dy;
162 if (dx == 0)
163 if (dy < 0)
164 return 6;
165 else if (dy > 0)
166 return 2;
167 else
168 return 6;
169 else if (dx > 0)
170 if (dy < 0)
171 return 7;
172 else if (dy > 0)
173 return 1;
174 else
175 return 0;
176 else if (dy < 0)
177 return 5;
178 else if (dy > 0)
179 return 3;
180 else
181 return 4;
182 }
183
moveplyr(OBJECTS * obp)184 BOOL moveplyr(OBJECTS * obp)
185 {
186 register OBJECTS *ob;
187 register BOOL rc;
188 register int oldx;
189 int multkey;
190
191 compplane = FALSE;
192 plyrplane = TRUE;
193
194 ob = obp;
195 currobx = ob->ob_index;
196
197 endstat = endsts[player];
198
199 if (endstat) {
200 --endcount;
201 if (endcount <= 0) {
202 if (playmode != PLAYMODE_ASYNCH && !quit)
203 swrestart();
204 swend(NULL, YES);
205 }
206 }
207
208 // sdh: use the cga (sdl) interface to
209 // read key status
210
211 multkey = Vid_GetGameKeys();
212
213 // Thanks to Kodath duMatri for fixing this :)
214
215 if (conf_harrykeys && ob->ob_orient)
216 if(multkey & (K_FLAPU | K_FLAPD))
217 multkey ^= K_FLAPU | K_FLAPD;
218
219 if (playmode == PLAYMODE_ASYNCH) {
220 asynput(multkey);
221 }
222
223 interpret(ob, multkey);
224
225 /*
226 if (dispcnt) {
227 ob->ob_flaps = 0;
228 ob->ob_bfiring = ob->ob_bombing = FALSE;
229 ob->ob_mfiring = NULL;
230 }*/
231
232 if ((ob->ob_state == CRASHED || ob->ob_state == GHOSTCRASHED)
233 && ob->ob_hitcount <= 0) {
234
235 // sdh: infinite lives in multiplayer mode
236
237 if (playmode != PLAYMODE_ASYNCH)
238 ++ob->ob_crashcnt;
239
240 if (endstat != WINNER
241 && (ob->ob_life <= QUIT
242 || (playmode != PLAYMODE_ASYNCH
243 && ob->ob_crashcnt >= MAXCRASH))) {
244 if (!endstat)
245 loser(ob);
246 } else {
247 initplyr(ob);
248 initdisp(YES);
249 if (endstat == WINNER) {
250 if (ctlbreak())
251 swend(NULL, YES);
252 winner(ob);
253 }
254 }
255 }
256
257 oldx = ob->ob_x;
258 rc = movepln(ob);
259
260 if (oldx <= SCR_LIMIT || oldx >= (MAX_X - SCR_LIMIT))
261 dispdx = 0;
262 else {
263 dispdx = ob->ob_x - oldx;
264 displx += dispdx;
265 }
266
267 if (!ob->ob_athome) {
268 setvdisp();
269
270 // sdh 26/10/2001: guages are now a single function
271
272 if (ob->ob_firing || ob->ob_bombing
273 || ob->ob_mfiring || ob->ob_bfiring)
274 dispguages(ob);
275 }
276
277 return rc;
278 }
279
280
281
282
interpret(OBJECTS * obp,int key)283 void interpret(OBJECTS * obp, int key)
284 {
285 register OBJECTS *ob;
286 register obstate_t state;
287
288 ob = obp;
289 ob->ob_flaps = 0;
290 ob->ob_bombing = ob->ob_bfiring = 0;
291 ob->ob_mfiring = ob->ob_firing = NULL;
292
293 state = ob->ob_state;
294
295 if (state != FLYING
296 && state != STALLED
297 && state != FALLING
298 && state != WOUNDED
299 && state != WOUNDSTALL
300 && state != GHOST
301 && state != GHOSTSTALLED)
302 return;
303
304 if (state != FALLING) {
305 if (endstat) {
306 if (endstat == LOSER && plyrplane)
307 gohome(ob);
308 return;
309 }
310
311 if (key & K_BREAK) {
312 ob->ob_life = QUIT;
313 ob->ob_home = FALSE;
314 if (ob->ob_athome) {
315 ob->ob_state = state =
316 state >= FINISHED ? GHOSTCRASHED : CRASHED;
317 ob->ob_hitcount = 0;
318 }
319 if (plyrplane)
320 quit = TRUE;
321 }
322
323 if (key & K_HOME)
324 if (state == FLYING || state == GHOST
325 || state == WOUNDED)
326 ob->ob_home = TRUE;
327 }
328
329 if ((countmove & 1)
330 || (state != WOUNDED && state != WOUNDSTALL)) {
331 if (key & K_FLAPU) {
332 ++ob->ob_flaps;
333 ob->ob_home = FALSE;
334 }
335
336 if (key & K_FLAPD) {
337 --ob->ob_flaps;
338 ob->ob_home = FALSE;
339 }
340
341 if (key & K_FLIP) {
342 ob->ob_orient = !ob->ob_orient;
343 ob->ob_home = FALSE;
344 }
345
346 if (key & K_DEACC) {
347 if (ob->ob_accel)
348 --ob->ob_accel;
349 ob->ob_home = FALSE;
350 }
351
352 if (key & K_ACCEL) {
353 if (ob->ob_accel < MAX_THROTTLE)
354 ++ob->ob_accel;
355 ob->ob_home = FALSE;
356 }
357 }
358
359 if ((key & K_SHOT) && state < FINISHED)
360 ob->ob_firing = ob;
361
362 if ((key & K_MISSILE) && state < FINISHED)
363 ob->ob_mfiring = ob;
364
365 if ((key & K_BOMB) && state < FINISHED)
366 ob->ob_bombing = TRUE;
367
368 if ((key & K_STARBURST) && state < FINISHED)
369 ob->ob_bfiring = TRUE;
370
371 if (key & K_SOUND)
372 if (plyrplane) {
373 if (soundflg) {
374 sound(0, 0, NULL);
375 swsound();
376 }
377 soundflg = !soundflg;
378 }
379
380 if (ob->ob_home)
381 gohome(ob);
382 }
383
movecomp(OBJECTS * obp)384 BOOL movecomp(OBJECTS * obp)
385 {
386 register OBJECTS *ob;
387 int rc;
388
389 compplane = TRUE;
390 plyrplane = FALSE;
391
392 ob = obp;
393 ob->ob_flaps = 0;
394 ob->ob_bfiring = ob->ob_bombing = FALSE;
395 ob->ob_mfiring = NULL;
396
397 currobx = ob->ob_index;
398 endstat = endsts[currobx];
399
400 if (!dispcnt)
401 ob->ob_firing = NULL;
402
403 switch (ob->ob_state) {
404
405 case WOUNDED:
406 case WOUNDSTALL:
407 if (countmove & 1)
408 break;
409
410 case FLYING:
411 case STALLED:
412 if (endstat) {
413 gohome(ob);
414 break;
415 }
416 if (!dispcnt)
417 swauto(ob);
418 break;
419
420 case CRASHED:
421 ob->ob_firing = NULL;
422 if (ob->ob_hitcount <= 0 && !endstat)
423 initcomp(ob);
424 break;
425
426 default:
427 ob->ob_firing = NULL;
428 break;
429 }
430
431
432 rc = movepln(ob);
433
434 return rc;
435 }
436
stallpln(OBJECTS * obp)437 static BOOL stallpln(OBJECTS * obp)
438 {
439 register OBJECTS *ob;
440
441 ob = obp;
442 ob->ob_ldx = ob->ob_ldy = ob->ob_orient = ob->ob_dx = 0;
443 ob->ob_angle = 7 * ANGLES / 8;
444 ob->ob_speed = 0;
445 ob->ob_dy = 0;
446 ob->ob_hitcount = STALLCOUNT;
447 ob->ob_state =
448 ob->ob_state >= GHOST ? GHOSTSTALLED :
449 ob->ob_state == WOUNDED ? WOUNDSTALL : STALLED;
450 ob->ob_athome = FALSE;
451
452 return TRUE;
453 }
454
455
456
movepln(OBJECTS * obp)457 BOOL movepln(OBJECTS * obp)
458 {
459 register OBJECTS *ob = obp;
460 register int nangle, nspeed, limit, update;
461 obstate_t state, newstate;
462 int x, y, stalled;
463 // int grv;
464
465 // sdh 28/4/2002: aargh! char is not neccesarily signed char,
466 // it seems. use int
467
468 static signed int gravity[] = {
469 0, -1, -2, -3, -4, -3, -2, -1,
470 0, 1, 2, 3, 4, 3, 2, 1
471 };
472
473 state = ob->ob_state;
474
475 switch (state) {
476 case FINISHED:
477 case WAITING:
478 return FALSE;
479
480 case CRASHED:
481 case GHOSTCRASHED:
482 --ob->ob_hitcount;
483 break;
484
485 case FALLING:
486 ob->ob_hitcount -= 2;
487 if ((ob->ob_dy < 0) && ob->ob_dx) {
488 if (ob->ob_orient ^ (ob->ob_dx < 0))
489 ob->ob_hitcount -= ob->ob_flaps;
490 else
491 ob->ob_hitcount += ob->ob_flaps;
492 }
493
494 if (ob->ob_hitcount <= 0) {
495 if (ob->ob_dy < 0) {
496 if (ob->ob_dx < 0)
497 ++ob->ob_dx;
498 else if (ob->ob_dx > 0)
499 --ob->ob_dx;
500 else
501 ob->ob_orient = !ob->ob_orient;
502 }
503
504 if (ob->ob_dy > -10)
505 --ob->ob_dy;
506 ob->ob_hitcount = FALLCOUNT;
507 }
508 ob->ob_angle = symangle(ob) * 2;
509 if (ob->ob_dy <= 0)
510 initsound(ob, S_FALLING);
511 break;
512
513 case STALLED:
514 newstate = FLYING;
515 goto commonstall;
516
517 case GHOSTSTALLED:
518 newstate = GHOST;
519 goto commonstall;
520
521 case WOUNDSTALL:
522 newstate = WOUNDED;
523
524 commonstall:
525 stalled = ob->ob_angle != (3 * ANGLES / 4)
526 || ob->ob_speed < gminspeed;
527 if (!stalled)
528 ob->ob_state = state = newstate;
529 goto controlled;
530
531 case FLYING:
532 case WOUNDED:
533 case GHOST:
534 stalled = ob->ob_y >= MAX_Y;
535 if (stalled) {
536 if (playmode == PLAYMODE_NOVICE) {
537 ob->ob_angle = (3 * ANGLES / 4);
538 stalled = FALSE;
539 } else {
540 stallpln(ob);
541 state = ob->ob_state;
542 }
543 }
544
545 controlled:
546 if (goingsun && plyrplane)
547 break;
548
549 if (ob->ob_life <= 0 && !ob->ob_athome
550 && (state == FLYING || state == STALLED
551 || state == WOUNDED
552 || state == WOUNDSTALL)) {
553 hitpln(ob);
554 scorepln(ob);
555 return movepln(ob);
556 }
557
558 if (ob->ob_firing)
559 initshot(ob, NULL);
560
561 if (ob->ob_bombing)
562 initbomb(ob);
563
564 if (ob->ob_mfiring)
565 initmiss(ob);
566
567 if (ob->ob_bfiring)
568 initburst(ob);
569
570 nangle = ob->ob_angle;
571 nspeed = ob->ob_speed;
572 update = ob->ob_flaps;
573
574 if (update) {
575 if (ob->ob_orient)
576 nangle -= update;
577 else
578 nangle += update;
579 nangle = (nangle + ANGLES) % ANGLES;
580 }
581
582 if (!(countmove & 0x0003)) {
583 if (!stalled && nspeed < gminspeed
584 && playmode != PLAYMODE_NOVICE) {
585 --nspeed;
586 update = TRUE;
587 } else {
588 limit = gminspeed
589 + ob->ob_accel + gravity[nangle];
590 if (nspeed < limit) {
591 ++nspeed;
592 update = TRUE;
593 } else if (nspeed > limit) {
594 --nspeed;
595 update = TRUE;
596 }
597 }
598 }
599
600 if (update) {
601 if (ob->ob_athome)
602 if (ob->ob_accel || ob->ob_flaps)
603 nspeed = gminspeed;
604 else
605 nspeed = 0;
606
607 else if (nspeed <= 0 && !stalled) {
608 if (playmode == PLAYMODE_NOVICE)
609 nspeed = 1;
610 else {
611 stallpln(ob);
612 return movepln(ob);
613 }
614 }
615
616 ob->ob_speed = nspeed;
617 ob->ob_angle = nangle;
618
619 if (stalled) {
620 ob->ob_dx = ob->ob_ldx = ob->ob_ldy = 0;
621 ob->ob_dy = -nspeed;
622 } else
623 setdxdy(ob,
624 nspeed * COS(nangle),
625 nspeed * SIN(nangle));
626 }
627
628 if (stalled) {
629 if (!--ob->ob_hitcount) {
630 ob->ob_orient = !ob->ob_orient;
631 ob->ob_angle = ((3 * ANGLES / 2)
632 - ob->ob_angle)
633 % ANGLES;
634 ob->ob_hitcount = STALLCOUNT;
635 }
636 }
637
638 if (!compplane) {
639 if (plyrplane
640 && ob->ob_speed >
641 (ob->ob_life % (MAXFUEL / 10))) {
642 setvdisp();
643
644 // sdh 26/10/2001: use new dispguages function
645
646 dispguages(ob);
647 }
648 ob->ob_life -= ob->ob_speed;
649 }
650
651 if (ob->ob_speed)
652 ob->ob_athome = FALSE;
653 break;
654 default:
655 break;
656 }
657
658 if (endstat == WINNER && plyrplane && goingsun)
659 ob->ob_newsym = symbol_plane_win[endcount / 18];
660 else if (ob->ob_state == FINISHED)
661 ob->ob_newsym = NULL;
662 else if (ob->ob_state == FALLING && !ob->ob_dx && ob->ob_dy < 0)
663 ob->ob_newsym = symbol_plane_hit[ob->ob_orient];
664 else
665 ob->ob_newsym = symbol_plane[ob->ob_orient][ob->ob_angle];
666
667 //ob->ob_newsym =
668 //ob->ob_state == FINISHED ? NULL :
669 //((ob->ob_state == FALLING
670 //&& !ob->ob_dx && ob->ob_dy < 0)
671 //? swhitsym[ob->ob_orient]
672 //: swplnsym[ob->ob_orient][ob->ob_angle]);
673
674 movexy(ob, &x, &y);
675
676 if (x < 0)
677 x = ob->ob_x = 0;
678 else if (x >= (MAX_X - 16))
679 x = ob->ob_x = MAX_X - 16;
680
681 if (!compplane
682 && (ob->ob_state == FLYING
683 || ob->ob_state == STALLED
684 || ob->ob_state == WOUNDED
685 || ob->ob_state == WOUNDSTALL)
686 && !endsts[player])
687 nearpln(ob);
688
689 deletex(ob);
690 insertx(ob, ob->ob_xnext);
691
692 if (ob->ob_bdelay)
693 --ob->ob_bdelay;
694 if (ob->ob_mdelay)
695 --ob->ob_mdelay;
696 if (ob->ob_bsdelay)
697 --ob->ob_bsdelay;
698
699 if (!compplane && ob->ob_athome && ob->ob_state == FLYING)
700 refuel(ob);
701
702 if (y < MAX_Y && y >= 0) {
703 if (ob->ob_state == FALLING
704 || ob->ob_state == WOUNDED
705 || ob->ob_state == WOUNDSTALL)
706 initsmok(ob);
707 setvdisp();
708 dispwobj(ob);
709 return plyrplane || ob->ob_state < FINISHED;
710 }
711
712 return FALSE;
713 }
714
715
716
adjustfall(OBJECTS * obp)717 static void adjustfall(OBJECTS * obp)
718 {
719 register OBJECTS *ob;
720
721 ob = obp;
722 if (!--ob->ob_life) {
723 if (ob->ob_dy < 0) {
724 if (ob->ob_dx < 0)
725 ++ob->ob_dx;
726 else if (ob->ob_dx > 0)
727 --ob->ob_dx;
728 }
729 if (ob->ob_dy > -10)
730 --ob->ob_dy;
731 ob->ob_life = BOMBLIFE;
732 }
733 }
734
735
moveshot(OBJECTS * obp)736 BOOL moveshot(OBJECTS * obp)
737 {
738 register OBJECTS *ob;
739 int x, y;
740
741 ob = obp;
742 deletex(ob);
743
744 --ob->ob_life;
745
746 if (ob->ob_life <= 0) {
747 deallobj(ob);
748 return FALSE;
749 }
750
751 movexy(ob, &x, &y);
752
753 if (y >= MAX_Y || y <= (int) ground[x]
754 || x < 0 || x >= MAX_X) {
755 deallobj(ob);
756 return FALSE;
757 }
758
759 insertx(ob, ob->ob_xnext);
760 ob->ob_newsym = &symbol_pixel;
761 return TRUE;
762 }
763
764
765
movebomb(OBJECTS * obp)766 BOOL movebomb(OBJECTS * obp)
767 {
768 register OBJECTS *ob;
769 int x, y;
770
771 ob = obp;
772
773 deletex(ob);
774
775 if (ob->ob_life < 0) {
776 deallobj(ob);
777 ob->ob_state = FINISHED;
778 setvdisp();
779 dispwobj(ob);
780 return FALSE;
781 }
782
783 adjustfall(ob);
784
785 if (ob->ob_dy <= 0)
786 initsound(ob, S_BOMB);
787
788 movexy(ob, &x, &y);
789
790 if (y < 0 || x < 0 || x >= MAX_X) {
791 deallobj(ob);
792 stopsound(ob);
793 ob->ob_state = FINISHED;
794 setvdisp();
795 dispwobj(ob);
796 return FALSE;
797 }
798
799 ob->ob_newsym = symbol_bomb[symangle(ob)];
800 insertx(ob, ob->ob_xnext);
801
802 if (y >= MAX_Y)
803 return FALSE;
804
805 setvdisp();
806 dispwobj(ob);
807 return TRUE;
808 }
809
810
811
movemiss(OBJECTS * obp)812 BOOL movemiss(OBJECTS * obp)
813 {
814 register OBJECTS *ob;
815 int x, y, angle;
816 OBJECTS *obt;
817
818 ob = obp;
819
820 deletex(ob);
821
822 if (ob->ob_life < 0) {
823 deallobj(ob);
824 ob->ob_state = FINISHED;
825 setvdisp();
826 dispwobj(ob);
827 return FALSE;
828 }
829
830 if (ob->ob_state == FLYING) {
831 obt = ob->ob_target;
832
833 if (obt != ob->ob_owner && (ob->ob_life & 1)) {
834 if (obt->ob_target)
835 obt = obt->ob_target;
836 aim(ob, obt->ob_x, obt->ob_y, NULL, NO);
837 angle = ob->ob_angle
838 =
839 (ob->ob_angle + ob->ob_flaps +
840 ANGLES) % ANGLES;
841 setdxdy(ob,
842 ob->ob_speed * COS(angle),
843 ob->ob_speed * SIN(angle));
844 }
845 movexy(ob, &x, &y);
846
847 --ob->ob_life;
848
849 if (ob->ob_life <= 0 || y >= ((MAX_Y * 3) / 2)) {
850 ob->ob_state = FALLING;
851 ++ob->ob_life;
852 }
853 } else {
854 adjustfall(ob);
855 ob->ob_angle = (ob->ob_angle + 1) % ANGLES;
856 movexy(ob, &x, &y);
857 }
858
859 if (y < 0 || x < 0 || x >= MAX_X) {
860 deallobj(ob);
861 ob->ob_state = FINISHED;
862 setvdisp();
863 dispwobj(ob);
864 return FALSE;
865 }
866
867 ob->ob_newsym = symbol_missile[ob->ob_angle];
868 insertx(ob, ob->ob_xnext);
869
870 if (y >= MAX_Y)
871 return FALSE;
872
873 setvdisp();
874 dispwobj(ob);
875 return TRUE;
876 }
877
878
879
moveburst(OBJECTS * obp)880 BOOL moveburst(OBJECTS * obp)
881 {
882 register OBJECTS *ob;
883 int x, y;
884
885 ob = obp;
886 deletex(ob);
887 if (ob->ob_life < 0) {
888 ob->ob_owner->ob_target = NULL;
889 deallobj(ob);
890 return FALSE;
891 }
892
893 adjustfall(ob);
894 movexy(ob, &x, &y);
895
896 if (y <= (int) ground[x] || x < 0 || x >= MAX_X) {
897 ob->ob_owner->ob_target = NULL;
898 deallobj(ob);
899 return FALSE;
900 }
901
902 ob->ob_owner->ob_target = ob;
903 ob->ob_newsym = symbol_burst[ob->ob_life & 1];
904 insertx(ob, ob->ob_xnext);
905
906 return y < MAX_Y;
907 }
908
909
910
911
movetarg(OBJECTS * obt)912 BOOL movetarg(OBJECTS * obt)
913 {
914 int r;
915 register OBJECTS *obp, *ob;
916
917 ob = obt;
918 obp = objtop;
919 ob->ob_firing = NULL;
920 if (gamenum
921 && ob->ob_state == STANDING
922 && (obp->ob_state == FLYING
923 || obp->ob_state == STALLED
924 || obp->ob_state == WOUNDED
925 || obp->ob_state == WOUNDSTALL)
926 && ob->ob_clr != obp->ob_clr
927 && (gamenum > 1 || (countmove & 0x0001))
928 && ((r = range(ob->ob_x, ob->ob_y, obp->ob_x, obp->ob_y)) > 0)
929 && r < targrnge)
930 initshot(ob, ob->ob_firing = obp);
931
932 --ob->ob_hitcount;
933
934 if (ob->ob_hitcount < 0)
935 ob->ob_hitcount = 0;
936
937 if (ob->ob_state == STANDING)
938 ob->ob_newsym = symbol_targets[ob->ob_orient];
939 else
940 ob->ob_newsym = symbol_target_hit;
941
942 return TRUE;
943 }
944
945
946
moveexpl(OBJECTS * obp)947 BOOL moveexpl(OBJECTS * obp)
948 {
949 register OBJECTS *ob;
950 int x, y;
951 register int orient;
952
953 ob = obp;
954 orient = ob->ob_orient;
955 deletex(ob);
956 if (ob->ob_life < 0) {
957 if (orient)
958 stopsound(ob);
959 deallobj(ob);
960 return FALSE;
961 }
962
963 --ob->ob_life;
964
965 if (ob->ob_life <= 0) {
966 if (ob->ob_dy < 0) {
967 if (ob->ob_dx < 0)
968 ++ob->ob_dx;
969 else if (ob->ob_dx > 0)
970 --ob->ob_dx;
971 }
972 if ((ob->ob_orient && ob->ob_dy > -10)
973 || (!ob->ob_orient && ob->ob_dy > -gminspeed))
974 --ob->ob_dy;
975 ob->ob_life = EXPLLIFE;
976 }
977
978 movexy(ob, &x, &y);
979
980 if (y <= (int) ground[x]
981 || x < 0 || x >= MAX_X) {
982 if (orient)
983 stopsound(ob);
984 deallobj(ob);
985 return (FALSE);
986 }
987 ++ob->ob_hitcount;
988
989 insertx(ob, ob->ob_xnext);
990 ob->ob_newsym = symbol_debris[ob->ob_orient];
991
992 return y < MAX_Y;
993 }
994
995
996
movesmok(OBJECTS * obp)997 BOOL movesmok(OBJECTS * obp)
998 {
999 register OBJECTS *ob;
1000 register obstate_t state;
1001
1002 ob = obp;
1003
1004 state = ob->ob_owner->ob_state;
1005
1006 --ob->ob_life;
1007
1008 if (ob->ob_life <= 0
1009 || (state != FALLING
1010 && state != WOUNDED
1011 && state != WOUNDSTALL
1012 && state != CRASHED)) {
1013 deallobj(ob);
1014 return FALSE;
1015 }
1016 ob->ob_newsym = &symbol_pixel;
1017
1018 return TRUE;
1019 }
1020
1021
1022
moveflck(OBJECTS * obp)1023 BOOL moveflck(OBJECTS * obp)
1024 {
1025 register OBJECTS *ob;
1026 int x, y;
1027
1028 ob = obp;
1029 deletex(ob);
1030
1031 if (ob->ob_life == -1) {
1032 setvdisp();
1033 dispwobj(ob);
1034 deallobj(ob);
1035 return FALSE;
1036 }
1037
1038 --ob->ob_life;
1039
1040 if (ob->ob_life <= 0) {
1041 ob->ob_orient = !ob->ob_orient;
1042 ob->ob_life = FLOCKLIFE;
1043 }
1044
1045 if (ob->ob_x < MINFLCKX || ob->ob_x > MAXFLCKX)
1046 ob->ob_dx = -ob->ob_dx;
1047
1048 movexy(ob, &x, &y);
1049 insertx(ob, ob->ob_xnext);
1050 ob->ob_newsym = symbol_flock[ob->ob_orient];
1051 setvdisp();
1052 dispwobj(ob);
1053 return TRUE;
1054 }
1055
1056
1057
movebird(OBJECTS * obp)1058 BOOL movebird(OBJECTS * obp)
1059 {
1060 register OBJECTS *ob;
1061 int x, y;
1062
1063 ob = obp;
1064
1065 deletex(ob);
1066
1067 if (ob->ob_life == -1) {
1068 deallobj(ob);
1069 return FALSE;
1070 } else if (ob->ob_life == -2) {
1071 ob->ob_dy = -ob->ob_dy;
1072 ob->ob_dx = (countmove & 7) - 4;
1073 ob->ob_life = BIRDLIFE;
1074 } else {
1075 --ob->ob_life;
1076
1077 if (ob->ob_life <= 0) {
1078 ob->ob_orient = !ob->ob_orient;
1079 ob->ob_life = BIRDLIFE;
1080 }
1081 }
1082
1083 movexy(ob, &x, &y);
1084
1085 insertx(ob, ob->ob_xnext);
1086 ob->ob_newsym = symbol_bird[ob->ob_orient];
1087 if (y >= MAX_Y || y <= (int) ground[x]
1088 || x < 0 || x >= MAX_X) {
1089 ob->ob_y -= ob->ob_dy;
1090 ob->ob_life = -2;
1091 return FALSE;
1092 }
1093 return TRUE;
1094 }
1095
1096
1097
1098
moveox(OBJECTS * ob)1099 BOOL moveox(OBJECTS * ob)
1100 {
1101 ob->ob_newsym = symbol_ox[ob->ob_state != STANDING];
1102 return TRUE;
1103 }
1104
1105
1106
1107
crashpln(OBJECTS * obp)1108 BOOL crashpln(OBJECTS * obp)
1109 {
1110 register OBJECTS *ob, *obo;
1111
1112 ob = obp;
1113
1114 if (ob->ob_dx < 0)
1115 ob->ob_angle = (ob->ob_angle + 2) % ANGLES;
1116 else
1117 ob->ob_angle = (ob->ob_angle + ANGLES - 2) % ANGLES;
1118
1119 ob->ob_state = ob->ob_state >= GHOST ? GHOSTCRASHED : CRASHED;
1120 ob->ob_athome = FALSE;
1121 ob->ob_dx = ob->ob_dy = ob->ob_ldx = ob->ob_ldy = ob->ob_speed = 0;
1122
1123 obo = &oobjects[ob->ob_index];
1124 ob->ob_hitcount = ((abs(obo->ob_x - ob->ob_x) < SAFERESET)
1125 && (abs(obo->ob_y - ob->ob_y) < SAFERESET))
1126 ? (MAXCRCOUNT << 1) : MAXCRCOUNT;
1127
1128 return TRUE;
1129 }
1130
1131
1132
hitpln(OBJECTS * obp)1133 BOOL hitpln(OBJECTS * obp)
1134 {
1135 register OBJECTS *ob;
1136
1137 ob = obp;
1138 ob->ob_ldx = ob->ob_ldy = 0;
1139 ob->ob_hitcount = FALLCOUNT;
1140 ob->ob_state = FALLING;
1141 ob->ob_athome = FALSE;
1142
1143 return TRUE;
1144 }
1145
1146
1147
1148
insertx(OBJECTS * ob,OBJECTS * obp)1149 BOOL insertx(OBJECTS * ob, OBJECTS * obp)
1150 {
1151 register OBJECTS *obs;
1152 register int obx;
1153
1154 obs = obp;
1155 obx = ob->ob_x;
1156 if (obx < obs->ob_x)
1157 do {
1158 obs = obs->ob_xprev;
1159 } while (obx < obs->ob_x);
1160 else {
1161 while (obx >= obs->ob_x)
1162 obs = obs->ob_xnext;
1163 obs = obs->ob_xprev;
1164 }
1165 ob->ob_xnext = obs->ob_xnext;
1166 ob->ob_xprev = obs;
1167 obs->ob_xnext->ob_xprev = ob;
1168 obs->ob_xnext = ob;
1169
1170 return TRUE;
1171 }
1172
1173
1174
deletex(OBJECTS * obp)1175 void deletex(OBJECTS * obp)
1176 {
1177 register OBJECTS *ob;
1178
1179 ob = obp;
1180 ob->ob_xnext->ob_xprev = ob->ob_xprev;
1181 ob->ob_xprev->ob_xnext = ob->ob_xnext;
1182 }
1183
1184
1185
1186 //---------------------------------------------------------------------------
1187 //
1188 // $Log: swmove.c,v $
1189 // Revision 1.6.2.1 2003/06/08 18:16:38 fraggle
1190 // Fix networking and some compile bugs
1191 //
1192 // Revision 1.6 2003/06/04 17:13:26 fraggle
1193 // Remove disprx, as it is implied from displx anyway.
1194 //
1195 // Revision 1.5 2003/06/04 17:02:37 fraggle
1196 // Remove some obfuscation and dead code
1197 //
1198 // Revision 1.4 2003/04/06 22:01:02 fraggle
1199 // Fix compile warnings
1200 //
1201 // Revision 1.3 2003/04/05 22:44:04 fraggle
1202 // Remove some useless functions from headers, make them static if they
1203 // are not used by other files
1204 //
1205 // Revision 1.2 2003/04/05 22:31:29 fraggle
1206 // Remove PLAYMODE_MULTIPLE and swnetio.c
1207 //
1208 // Revision 1.1.1.1 2003/02/14 19:03:15 fraggle
1209 // Initial Sourceforge CVS import
1210 //
1211 //
1212 // sdh 14/2/2003: change license header to GPL
1213 // autohome on harry keys mode fixed.
1214 // sdh 27/06/2002: move to new sopsym_t for symbols
1215 // sdh 26/03/2002: change CGA_ to Vid_
1216 // sdh 27/10/2001: fix refueling i broke with the guages change yesterday
1217 // sdh 26/10/2001: use new dispguages function
1218 // sdh 21/10/2001: use new obtype_t and obstate_t
1219 // sdh 21/10/2001: reformatted with indent. edited some code by hand to
1220 // make it more readable
1221 // sdh 19/10/2001: removed all externs, these are now in headers
1222 // shuffled some functions around to shut up compiler
1223 // sdh 18/10/2001: converted all functions in this file to ANSI-style arguments
1224 //
1225 // 87-04-09 Delay between starbursts.
1226 // 87-04-04 Missile and starburst support.
1227 // 87-04-01 Missiles.
1228 // 87-03-31 Allow wounded plane to fly home
1229 // 87-03-30 Novice Player
1230 // 87-03-12 Computer plane heads home at end.
1231 // 87-03-12 Prioritize bombs/shots over flaps.
1232 // 87-03-12 Proper ASYCHRONOUS end of game.
1233 // 87-03-12 Crashed planes stay longer at home.
1234 // 87-03-12 Wounded airplanes.
1235 // 87-03-09 Microsoft compiler.
1236 // 85-10-31 Atari
1237 // 84-02-07 Development
1238 //
1239 //---------------------------------------------------------------------------
1240
1241
1242