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