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