1 /* 2 swinit - SW initialization 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 Modification History: 16 84-02-02 Development 17 85-10-31 Atari 18 87-01-09 BMB standard help text. 19 Multiple serial ports. 20 87-03-09 Microsoft compiler. 21 87-03-11 Smaller fuel tank explosions. 22 87-03-12 Wounded airplanes. 23 87-03-30 Novice player. 24 87-03-31 Missiles 25 87-03-31 Less x-movement in explosions 26 87-04-04 Missile and starburst support 27 87-04-05 Less x-movement in explosions 28 87-04-06 Computer plane avoiding oxen. 29 87-04-09 Fix to initial missile path. 30 Delay between starbursts 31 96-12-26 New network version. 32 Remove keyboard prompts. 33 Speed up game a bit. 34 99-01-24 1999 copyright. 35 Disable network support. 36 2000-10-29 Copyright update. 37 Comment out multiplayer selection 38 on startup. 39 2003-01-27 GNU General Public License. 40 2003-02-04 GNU public license in -? 41 */ 42 #include "sw.h" 43 44 45 extern int _systype; /* operating environment */ 46 extern int playmode; /* Mode of play */ 47 extern GAMES swgames[], *currgame; /* Game parameters and current game */ 48 extern GRNDTYPE ground[]; /* Ground height by pixel */ 49 extern GRNDTYPE orground[]; /* Original ground height by pixel */ 50 51 52 extern MULTIO *multbuff; /* Communications buffer */ 53 54 extern BOOL hires; /* High res flag */ 55 extern BOOL titleflg; /* Title flag */ 56 extern BOOL disppos; /* Display position flag */ 57 extern int keydelay; /* Number of displays per keystroke*/ 58 extern int soundflg; /* Sound flag */ 59 extern BOOL repflag; /* Report statistics flag */ 60 extern BOOL joystick; /* Joy stick being used */ 61 extern BOOL ibmkeybd; /* IBM keyboard or look-alike */ 62 extern int multtick; /* Multiple user tick delay */ 63 extern BOOL inplay; /* Currently playing flag */ 64 extern int koveride; /* Keyboard override index number */ 65 extern int missok; /* Missiles supported */ 66 67 extern int gamenum; /* Current game number */ 68 extern int gmaxspeed, gminspeed; /* Speed range based on game number */ 69 extern int targrnge; /* Target range based on game number*/ 70 71 extern int displx, disprx; /* Display left and right */ 72 extern char auxdisp[]; /* Auxiliary display area */ 73 extern BOOL dispinit; /* Initalized display flag. */ 74 extern char *histin, *histout; /* History input and output files */ 75 76 extern OBJECTS *nobjects; /* Objects list. */ 77 extern OBJECTS oobjects[]; /* Original plane object description*/ 78 extern OBJECTS *objbot, *objtop, /* Top and bottom of object list */ 79 *objfree, /* Free list */ 80 *deltop, *delbot; /* Newly deallocated objects */ 81 extern OBJECTS *targets[]; /* Target status array */ 82 extern int numtarg[]; /* number of active targets */ 83 extern OBJECTS topobj, botobj; /* Top and Bottom of object by x lst*/ 84 extern int player; /* Pointer to player's object */ 85 extern BOOL plyrplane; /* Current object is the player */ 86 extern BOOL compplane; /* Current object is a comp plane */ 87 extern int currobx; /* Current object index */ 88 extern OLDWDISP wdisp[]; /* World display status */ 89 extern int splatox; /* Display splatted ox */ 90 extern int oxsplatted; /* An ox has been splotted */ 91 extern int movetick, movemax; /* Move timing */ 92 93 extern int dispcomp(), /* Display and move functions */ 94 movecomp(), 95 dispplyr(), 96 moveplyr(), 97 moveshot(), 98 dispbomb(), 99 movebomb(), 100 movetarg(), 101 disptarg(), 102 moveexpl(), 103 dispexpl(), 104 movesmok(), 105 movebird(), 106 dispbird(), 107 moveflck(), 108 dispflck(), 109 moveox(), 110 movemiss(), 111 dispmiss(), 112 moveburst(), 113 dispburst(); 114 115 extern OBJECTS *allocobj(); 116 117 extern int swbreak(), swtick(), swshfprt(), swkeyint(); 118 extern int counttick, countmove; /* Performance counters */ 119 120 121 extern int sintab[]; /* sine table based on angles */ 122 123 extern jmp_buf envrestart; /* Restart environment for restart */ 124 /* long jump. */ 125 126 extern int endsts[]; /* End of game status and move count*/ 127 extern int endcount; 128 extern BOOL goingsun; /* Heading for the sun flag */ 129 extern OBJECTS *compnear[]; /* Array of planes near computers*/ 130 extern unsigned explseed; /* explosion seed */ 131 132 extern char *multfile; /* Multi user files */ 133 extern char *cmndfile; 134 extern unsigned multaddr; /* Multiple user diskette adapter */ 135 /* address */ 136 137 extern int maxcrash; /* Maximum number of crashes */ 138 139 extern int ctlbflag; /* Control break has been pressed */ 140 141 static int savescore; /* save players score on restart */ 142 static BOOL ghost; /* ghost display flag */ 143 144 static char *helptxt[] = { /* Help text */ 145 "", 146 "SOPWITH, (The Author's Edition)", 147 "(c) Copyright 1984-2003 David L. Clark", 148 "Modification Date: February 4, 2003", 149 "", 150 "This program is free software; you can redistribute it and/or modify it under", 151 "the terms of the GNU General Public License as published by the Free Software", 152 "Foundation; either version 2 of the License, or (at your option) any later", 153 "version. This program is distributed in the hope that it will be useful,", 154 "but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY", 155 "or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for", 156 "more details. You should have received a copy of the GNU General Public", 157 "License along with this program; if not, write to the Free Software Foundation,", 158 "Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.", 159 "", 160 "Usage: sopwith [options]", 161 "The options are:", 162 " -n : novice single player", 163 " -s : single player", 164 " -c : single player against computer", 165 /* 166 " -m : multiple players on a network", 167 */ 168 " -a : 2 players over asynchrounous communications line", 169 " (Only one of -n, -s, -c, -a may be specified)", 170 " -k : keyboard only", 171 " -j : joystick and keyboard", 172 " (Only one of -k and -j may be specified)", 173 /* 174 " -i : IBM PC keyboard", 175 */ 176 " -q : begin game with sound off", 177 /* 178 " -r : resets the multiuser communications file after an abnormal", 179 " end of a game", 180 " -d*: overrides the default drive C as the device containing the", 181 " communications file", 182 */ 183 " -p#: overrides asynchronous port 1 as the asynchrounous port", 184 " to use", 185 0 186 }; 187 188 189 190 swinit( argc, argv ) 191 int argc; 192 char *argv[]; 193 { 194 BOOL reset = FALSE; 195 BOOL n = FALSE; 196 BOOL s = FALSE; 197 BOOL c = FALSE; 198 BOOL m = FALSE; 199 BOOL a = FALSE; 200 BOOL k = FALSE; 201 int modeset, keyset; 202 char *device = "\0 "; 203 204 205 if ( getflags( &argc, &argv, 206 /*---- 96/12/27------ 207 "n&s&c&m&a&k&i&j&q&h*v*r&d*f*n*t#w&y#e&g#x&:", 208 &n, &s, &c, &m, &a, &k, &ibmkeybd, &joystick, &soundflg, 209 &histout, &histin, &reset, &device, 210 &multfile, &cmndfile, &multtick, &hires, &keydelay, 211 &repflag, &gamenum, &missok ) 212 ------ 96/12/27----*/ 213 /*---- 99/01/24------ 214 "n&s&c&m&a&k&j&q&h*v*r&d*f*t#w&y#e&g#x&:", 215 &n, &s, &c, &m, &a, &k, &joystick, &soundflg, 216 &histout, &histin, &reset, &device, 217 &multfile, &multtick, &hires, &keydelay, 218 &repflag, &gamenum, &missok ) 219 ------ 99/01/24----*/ 220 "n&s&c&a&k&j&q&x&:", 221 &n, &s, &c, &a, &k, &joystick, &soundflg, 222 &missok ) 223 || ( ( modeset = n + s + c + m + a ) > 1 ) 224 || ( ( keyset = joystick + k ) > 1 ) ) { 225 disphelp( helptxt ); 226 exit( 1 ); 227 } 228 229 soundflg = !soundflg; 230 if ( modeset && keyset ) 231 titleflg = TRUE; 232 233 movemax=15; 234 initseed(); 235 explseed = histinit( explseed ); 236 initsndt(); 237 intsoff(); 238 _intsetup( BREAKINT, swbreak, csseg(), dsseg() ); 239 _intsetup( CLOCKINT, swtick, csseg(), dsseg() ); 240 initgrnd(); 241 swtitln(); 242 intson(); 243 244 if ( modeset ) 245 playmode = n ? NOVICE 246 : ( s ? SINGLE 247 : ( c ? COMPUTER 248 : ( m ? MULTIPLE : ASYNCH ) ) ); 249 else 250 getmode(); 251 252 if ( !keyset ) 253 getkey(); 254 255 if ( ( playmode == MULTIPLE ) || ( playmode == ASYNCH ) ) { 256 maxcrash = MAXCRASH * 2; 257 if ( playmode == MULTIPLE ) 258 init1mul( reset, device ); 259 else 260 init1asy(); 261 initgrnd(); 262 initobjs(); 263 if ( playmode == MULTIPLE ) 264 init2mul(); 265 else 266 init2asy(); 267 inittarg(); 268 if ( currgame->gm_specf ) 269 ( *currgame->gm_specf ) (); 270 initdisp( NO ); 271 if ( keydelay == -1 ) 272 keydelay = 1; 273 } else { 274 if ( keydelay == -1 ) 275 keydelay = 1; 276 maxcrash = MAXCRASH; 277 currgame = &swgames[0]; 278 clrprmpt(); 279 initobjs(); 280 initplyr( NULL ); 281 initcomp( NULL ); 282 initcomp( NULL ); 283 initcomp( NULL ); 284 inittarg(); 285 if ( currgame->gm_specf ) 286 ( *currgame->gm_specf ) (); 287 initdisp( NO ); 288 } 289 290 initflck(); 291 initoxen(); 292 293 initgdep(); 294 295 intsoff(); 296 _intsetup( PRINTINT, swshfprt, csseg(), dsseg() ); 297 koveride = _intsetup( KEYINT, swkeyint, csseg(), dsseg() ); 298 inplay = TRUE; 299 intson(); 300 } 301 302 303 304 static disphelp( hp ) 305 char **hp; 306 { 307 register char **h; 308 309 h = hp; 310 puts( "\r\n" ); 311 while ( *h ) { 312 puts( *h++ ); 313 puts( "\r\n" ); 314 } 315 } 316 317 318 319 320 321 initseed() 322 { 323 #ifdef IBMPC 324 while ( !explseed ) { 325 outportb( 0x43, 0 ); 326 explseed = ( 0x00FF & inportb( 0x40 ) ) 327 | ( 0xFF00 & ( inportb( 0x40 ) << 8 ) ); 328 } 329 #endif 330 #ifdef ATARI 331 long trap14(); 332 333 explseed = trap14( 17 ); 334 #endif 335 } 336 337 338 339 340 341 swrestart() 342 { 343 register OBJECTS *ob; 344 register int tickwait, inc; 345 346 if ( endsts[player] == WINNER ) { 347 ob = &nobjects[player]; 348 inc = 0; 349 while ( ob->ob_crashcnt++ < maxcrash ) { 350 ob->ob_score += ( inc += 25 ); 351 setvdisp(); 352 dispcgge( ob ); 353 dispscore( ob ); 354 intsoff(); 355 tickwait = 5; 356 counttick = 0; 357 intson(); 358 while ( counttick < tickwait ); 359 } 360 ++gamenum; 361 savescore = ob->ob_score; 362 } else { 363 gamenum = 0; 364 savescore = 0; 365 } 366 367 initsndt(); 368 initgrnd(); 369 initobjs(); 370 initplyr( NULL ); 371 initcomp( NULL ); 372 initcomp( NULL ); 373 initcomp( NULL ); 374 inittarg(); 375 if ( currgame->gm_specf ) 376 ( *currgame->gm_specf ) (); 377 378 initdisp( NO ); 379 initflck(); 380 initoxen(); 381 initgdep(); 382 383 longjmp( envrestart, 0 ); 384 } 385 386 387 388 initgdep() 389 { 390 391 gmaxspeed = MAX_SPEED + gamenum; 392 gminspeed = MIN_SPEED + gamenum; 393 394 targrnge = 150; 395 if ( gamenum < 6 ) 396 targrnge -= 15 * ( 6 - gamenum ); 397 targrnge *= targrnge; 398 } 399 400 401 402 403 404 405 clrprmpt() 406 { 407 #ifdef IBMPC 408 register int i; 409 struct regval reg; 410 411 for ( i = 0; i < 4; ++i ) { 412 swposcur( 0, 20 + i ); 413 reg.axr = 0x0A20; 414 reg.bxr = 0; 415 reg.cxr = hires ? 80 : 40; 416 sysint( 0x10, ®, ® ); 417 } 418 swposcur( 0, 20 ); 419 #endif 420 421 #ifdef ATARI 422 register int i; 423 424 for ( i = 0; i < 4; ++i ) { 425 swposcur( 0, 20 + i ); 426 puts( "\33K" ); 427 } 428 swposcur( 0, 20 ); 429 #endif 430 } 431 432 433 434 435 static getkey() 436 { 437 register char key; 438 439 /*----------------97/12/27-------------- 440 clrprmpt(); 441 puts( "Key: 1 - Joystick with IBM Keyboard\r\n" ); 442 puts( " 2 - Joystick with non-IBM Keyboard\r\n" ); 443 puts( " 3 - IBM Keyboard only\r\n" ); 444 puts( " 4 - Non-IBM keyboard only\r\n" ); 445 FOREVER { 446 if ( ctlbreak() ) 447 swend( NULL, NO ); 448 if ( ( ( key = swgetc() & 0x00FF ) < '1' ) 449 || ( key > '4' ) ) 450 continue; 451 joystick = ( key <= '2' ); 452 ibmkeybd = ( key == '1' ) || ( key == '3' ); 453 return; 454 } 455 ------------------97/12/27--------------*/ 456 clrprmpt(); 457 puts( "Key: K - Keyboard Only\r\n" ); 458 puts( " J - Joystick and Keyboard\r\n" ); 459 FOREVER { 460 if ( ctlbreak() ) 461 swend( NULL, NO ); 462 if ( ( ( key = toupper(swgetc() & 0x00FF) ) != 'K' ) 463 && ( key != 'J' ) ) 464 continue; 465 joystick = key == 'J'; 466 ibmkeybd = 1; 467 return; 468 } 469 } 470 471 472 473 474 475 static getmode() 476 { 477 clrprmpt(); 478 puts( "Key: S - single player\r\n" ); 479 puts( " C - single player against computer\r\n" ); 480 if ( _systype == PCDOS ) { 481 /*--------------- 2000/10/29 ----------------------- 482 puts( " M - multiple players on network\r\n" ); 483 ----------------- 2000/10/29 ---------------------*/ 484 puts( " A - 2 players on asynchronous line" ); 485 } 486 FOREVER { 487 if ( ctlbreak() ) 488 swend( NULL, NO ); 489 switch ( toupper( swgetc() & 0x00FF ) ) { 490 case 'S': 491 clrprmpt(); 492 puts( "Key: N - novice player\r\n" ); 493 puts( " E - expert player\r\n" ); 494 FOREVER { 495 if ( ctlbreak() ) 496 swend( NULL, NO ); 497 switch ( toupper( swgetc() 498 & 0x00FF ) ){ 499 case 'N': 500 playmode = NOVICE; 501 return; 502 case 'E': 503 playmode = SINGLE; 504 return; 505 } 506 } 507 case 'M': 508 /*----- 2000/10/29 ---------- 509 if ( _systype == PCDOS ) { 510 playmode = MULTIPLE; 511 return; 512 } 513 ------- 2000/10/29 --------*/ 514 break; 515 case 'C': 516 playmode = COMPUTER; 517 return; 518 case 'A': 519 if ( _systype == PCDOS ) { 520 playmode = ASYNCH; 521 return; 522 } 523 break; 524 default: 525 break; 526 } 527 } 528 } 529 530 531 532 533 getgame() 534 { 535 register int game; 536 537 clrprmpt(); 538 puts( " Key a game number" ); 539 FOREVER { 540 if ( ctlbreak() ) 541 swend( NULL, NO ); 542 if ( ( ( game = ( swgetc() & 0x00FF ) - '0' ) >= 0 ) 543 && ( game <= MAX_GAME ) ) 544 return( game ); 545 } 546 } 547 548 549 550 551 BOOL ctlbreak() 552 { 553 return( ctlbflag ); 554 } 555 556 557 558 559 static initgrnd() 560 { 561 movmem( orground, ground, sizeof( GRNDTYPE ) * MAX_X ); 562 } 563 564 565 566 567 initdisp( reset ) 568 BOOL reset; 569 { 570 register OBJECTS *ob; 571 OBJECTS ghostob; 572 extern char swghtsym[]; 573 574 splatox = oxsplatted = 0; 575 if ( !reset ) { 576 clrdispa(); 577 setadisp(); 578 dispworld(); 579 swtitlf(); 580 ghost = FALSE; 581 } 582 movedisp(); 583 setvdisp(); 584 initwobj(); 585 initscore(); 586 587 ob = &nobjects[player]; 588 if ( ghost ) { 589 ghostob.ob_type = DUMMYTYPE; 590 ghostob.ob_symhgt = ghostob.ob_symwdt = 8; 591 ghostob.ob_clr = ob->ob_clr; 592 ghostob.ob_newsym = swghtsym; 593 swputsym( GHOSTX, 12, &ghostob ); 594 } else { 595 dispfgge( ob ); 596 dispbgge( ob ); 597 dispmgge( ob ); 598 dispsbgge( ob ); 599 dispsgge( ob ); 600 dispcgge( ob ); 601 } 602 dispinit = TRUE; 603 } 604 605 606 607 static initscore() 608 { 609 if ( savescore ) { 610 nobjects[0].ob_score = savescore; 611 savescore = 0; 612 } 613 614 dispscore( &nobjects[0] ); 615 if ( ( ( playmode == MULTIPLE ) || ( playmode == ASYNCH ) ) 616 && ( multbuff->mu_maxplyr > 1 ) ) 617 dispscore( &nobjects[1] ); 618 } 619 620 621 622 623 dispcgge( ob ) 624 OBJECTS *ob; 625 { 626 dispgge( CGUAGEX, maxcrash - ob->ob_crashcnt, maxcrash, ob->ob_clr ); 627 } 628 629 630 631 632 dispfgge( ob ) 633 OBJECTS *ob; 634 { 635 dispgge( FGUAGEX, ob->ob_life >> 4, MAXFUEL >> 4, ob->ob_clr ); 636 } 637 638 639 640 641 dispbgge( ob ) 642 OBJECTS *ob; 643 { 644 dispgge( BGUAGEX, ob->ob_bombs, MAXBOMBS, 3 - ob->ob_clr ); 645 } 646 647 648 649 650 dispsgge( ob ) 651 OBJECTS *ob; 652 { 653 dispgge( SGUAGEX, ob->ob_rounds, MAXROUNDS, 3 ); 654 } 655 656 657 658 659 dispmgge( ob ) 660 OBJECTS *ob; 661 { 662 dispgge( MGUAGEX, ob->ob_missiles, MAXMISSILES, ob->ob_clr ); 663 } 664 665 666 667 668 dispsbgge( ob ) 669 OBJECTS *ob; 670 { 671 dispgge( SBGUAGEX, ob->ob_bursts, MAXBURSTS, 3 - ob->ob_clr ); 672 } 673 674 675 676 677 static dispgge( x, cury, maxy, clr ) 678 int x, cury, maxy, clr; 679 { 680 register int y; 681 682 if ( ghost ) 683 return; 684 685 cury = cury * 10 / maxy - 1; 686 if ( cury > 9 ) 687 cury = 9; 688 for ( y = 0; y <= cury; ++y ) 689 swpntsym( x, y, clr ); 690 for ( ; y <= 9; ++y ) 691 swpntsym( x, y, 0 ); 692 } 693 694 695 696 static dispworld() 697 { 698 register int x, y, dx, maxh, sx; 699 700 dx = 0; 701 sx = SCR_CENTR; 702 703 maxh = 0; 704 y = 0; 705 for ( x = 0; x < MAX_X; ++x ) { 706 707 if ( ground[x] > maxh ) 708 maxh = ground[x]; 709 710 if ( ( ++dx ) == WRLD_RSX ) { 711 maxh /= WRLD_RSY; 712 if ( maxh == y ) 713 swpntsym( sx, maxh, 7 ); 714 else 715 if ( maxh > y ) 716 for ( ++y; y <= maxh; ++y ) 717 swpntsym( sx, y, 7 ); 718 else 719 for ( --y; y >= maxh; --y ) 720 swpntsym( sx, y, 7 ); 721 y = maxh; 722 swpntsym( sx, 0, 11 ); 723 ++sx; 724 dx = maxh = 0; 725 } 726 } 727 maxh = MAX_Y / WRLD_RSY; 728 for ( y = 0; y <= maxh; ++y ) { 729 swpntsym( SCR_CENTR, y, 11 ); 730 swpntsym( sx, y, 11 ); 731 } 732 733 for ( x = 0; x < SCR_WDTH; ++x ) 734 swpntsym( x, (SCR_MNSH+2), 7 ); 735 } 736 737 738 739 740 741 static initwobj() 742 { 743 int x; 744 register OBJECTS *ob; 745 register OLDWDISP *ow; 746 747 ow = wdisp; 748 ob = nobjects; 749 for ( x = 0; x < MAX_OBJS; ++x, ow++, ob++ ) 750 ow->ow_xorplot = ob->ob_drwflg = ob->ob_delflg = 0; 751 752 for ( x = 0; x < MAX_TARG; ++x ) 753 if ( ( ob = targets[x] ) && ( ob->ob_state != FINISHED ) ) 754 dispwobj( ob ); 755 756 } 757 758 759 760 static movedisp() 761 { 762 #ifdef IBMPC 763 swsetblk( 0, SCR_SEGM, 0x1000, 0 ); 764 swsetblk( SCR_ROFF, SCR_SEGM, 0x1000, 0 ); 765 movblock( auxdisp, dsseg(), 0x1000, SCR_SEGM, 0x1000 ); 766 movblock( auxdisp + 0x1000, dsseg(), 0x3000, SCR_SEGM, 0x1000 ); 767 #endif 768 769 #ifdef ATARI 770 long trap14(), vidram; 771 772 vidram = trap14( 3 ); 773 setmem( vidram, 0x4000, 0 ); 774 movmem( auxdisp, vidram + 0x4000, 0x4000 ); 775 #endif 776 } 777 778 779 780 781 static clrdispa() 782 { 783 #ifdef IBMPC 784 setmem( auxdisp, 0x2000, 0 ); 785 #endif 786 787 #ifdef ATARI 788 setmem( auxdisp, 0x4000, 0 ); 789 #endif 790 } 791 792 793 794 795 static initobjs() 796 { 797 register OBJECTS *ob; 798 register int o; 799 800 topobj.ob_xnext = topobj.ob_next = &botobj; 801 botobj.ob_xprev = botobj.ob_prev = &topobj; 802 topobj.ob_x = -32767; 803 botobj.ob_x = 32767; 804 805 objbot = objtop = deltop = delbot = NULL; 806 objfree = ob = nobjects; 807 808 for ( o = 0; o < MAX_OBJS; ++o ) { 809 ob->ob_next = ob + 1; 810 (ob++)->ob_index = o; 811 } 812 813 (--ob)->ob_next = NULL; 814 815 } 816 817 818 819 initcomp( obp ) 820 OBJECTS *obp; 821 { 822 register OBJECTS *ob; 823 OBJECTS *initpln(); 824 825 826 ob = initpln( obp ); 827 if ( !obp ) { 828 ob->ob_drawf = dispcomp; 829 ob->ob_movef = movecomp; 830 ob->ob_clr = 2; 831 if ( ( playmode != MULTIPLE ) && ( playmode != ASYNCH ) ) 832 ob->ob_owner = &nobjects[1]; 833 else 834 if ( ob->ob_index == 1 ) 835 ob->ob_owner = ob; 836 else 837 ob->ob_owner = ob - 2; 838 movmem( ob, &oobjects[ob->ob_index], sizeof( OBJECTS ) ); 839 } 840 if ( ( playmode == SINGLE ) || ( playmode == NOVICE ) ){ 841 ob->ob_state = FINISHED; 842 deletex( ob ); 843 } 844 } 845 846 847 848 initplyr( obp ) 849 OBJECTS *obp; 850 { 851 register OBJECTS *ob; 852 OBJECTS *initpln(); 853 854 ob = initpln( obp ); 855 if ( !obp ) { 856 ob->ob_drawf = dispplyr; 857 ob->ob_movef = moveplyr; 858 ob->ob_clr = ob->ob_index % 2 + 1; 859 ob->ob_owner = ob; 860 movmem( ob, &oobjects[ob->ob_index], sizeof( OBJECTS ) ); 861 goingsun = FALSE; 862 endcount = 0; 863 } 864 865 displx = ob->ob_x - SCR_CENTR; 866 disprx = displx + SCR_WDTH - 1; 867 868 swflush(); 869 } 870 871 872 873 static int inits[2] = { 0, 7 }; 874 static int initc[4] = { 0, 7, 1, 6 }; 875 static int initm[8] = { 0, 7, 3, 4, 2, 5, 1, 6 }; 876 877 878 879 OBJECTS *initpln( obp ) 880 OBJECTS *obp; 881 { 882 register OBJECTS *ob; 883 register int x, height, minx, maxx, n; 884 885 if ( !obp ) 886 ob = allocobj(); 887 else 888 ob = obp; 889 890 switch ( playmode ) { 891 case SINGLE: 892 case NOVICE: 893 n = inits[ob->ob_index]; 894 break; 895 case MULTIPLE: 896 case ASYNCH: 897 n = initm[ob->ob_index]; 898 break; 899 case COMPUTER: 900 n = initc[ob->ob_index]; 901 break; 902 } 903 904 ob->ob_type = PLANE; 905 906 ob->ob_x = currgame->gm_x[n]; 907 minx = ob->ob_x; 908 maxx = ob->ob_x + 20; 909 height = 0; 910 for ( x = minx; x <= maxx; ++x ) 911 if ( ground[x] > height ) 912 height = ground[x]; 913 ob->ob_y = height + 13; 914 ob->ob_lx = ob->ob_ly = ob->ob_speed = ob->ob_flaps = ob->ob_accel 915 = ob->ob_hitcount = ob->ob_bdelay = ob->ob_mdelay 916 = ob->ob_bsdelay = 0; 917 setdxdy( ob, 0, 0 ); 918 ob->ob_orient = currgame->gm_orient[n]; 919 ob->ob_angle = ( ob->ob_orient ) ? ( ANGLES / 2 ) : 0; 920 ob->ob_target = ob->ob_firing = ob->ob_mfiring = NULL; 921 ob->ob_bombing = ob->ob_bfiring = ob->ob_home = FALSE; 922 ob->ob_symhgt = SYM_HGHT; 923 ob->ob_symwdt = SYM_WDTH; 924 ob->ob_athome = TRUE; 925 if ( ( !obp ) || ( ob->ob_state == CRASHED ) 926 || ( ob->ob_state == GHOSTCRASHED ) ) { 927 ob->ob_rounds = MAXROUNDS; 928 ob->ob_bombs = MAXBOMBS; 929 ob->ob_missiles = MAXMISSILES; 930 ob->ob_bursts = MAXBURSTS; 931 ob->ob_life = MAXFUEL; 932 } 933 if ( !obp ) { 934 ob->ob_score = ob->ob_updcount = ob->ob_crashcnt 935 = endsts[ob->ob_index] = 0; 936 compnear[ob->ob_index] = NULL; 937 insertx( ob, &topobj ); 938 } else { 939 deletex( ob ); 940 insertx( ob, ob->ob_xnext ); 941 } 942 943 if ( ( ( playmode == MULTIPLE ) || ( playmode == ASYNCH ) ) 944 && ( ob->ob_crashcnt >= maxcrash ) ) { 945 ob->ob_state = GHOST; 946 if ( ob->ob_index == player ) 947 ghost = TRUE; 948 } else 949 ob->ob_state = FLYING; 950 951 return( ob ); 952 } 953 954 955 956 initshot( obop, targ ) 957 OBJECTS *obop, *targ; 958 { 959 register OBJECTS *ob, *obo; 960 int nangle, nspeed, dx, dy, r, bspeed, x, y; 961 962 963 if ( ( !targ ) && ( !compplane ) && ( !obo->ob_rounds )) 964 return; 965 966 if ( !( ob = allocobj() ) ) 967 return; 968 969 obo = obop; 970 if ( playmode != NOVICE ) 971 --obo->ob_rounds; 972 973 bspeed = BULSPEED + gamenum; 974 975 if ( targ ) { 976 x = targ->ob_x + ( targ->ob_dx << 2 ); 977 y = targ->ob_y + ( targ->ob_dy << 2 ); 978 dx = x - obo->ob_x; 979 dy = y - obo->ob_y; 980 if ( ( r = isrange( x, y, obo->ob_x, obo->ob_y ) ) < 1 ) { 981 deallobj( ob ); 982 return; 983 } 984 ob->ob_dx = ( dx * bspeed ) / r; 985 ob->ob_dy = ( dy * bspeed ) / r; 986 ob->ob_ldx = ob->ob_ldy = 0; 987 } else { 988 nspeed = obo->ob_speed + bspeed; 989 nangle = obo->ob_angle; 990 setdxdy( ob, nspeed * COS( nangle ), 991 nspeed * SIN( nangle ) ); 992 } 993 994 ob->ob_type = SHOT; 995 ob->ob_x = obo->ob_x + SYM_WDTH / 2; 996 ob->ob_y = obo->ob_y - SYM_HGHT / 2; 997 ob->ob_lx = obo->ob_lx; 998 ob->ob_ly = obo->ob_ly; 999 1000 1001 ob->ob_life = BULLIFE; 1002 ob->ob_owner = obo; 1003 ob->ob_clr = obo->ob_clr; 1004 ob->ob_symhgt = ob->ob_symwdt = 1; 1005 ob->ob_drawf = NULL; 1006 ob->ob_movef = moveshot; 1007 ob->ob_speed = 0; 1008 1009 insertx( ob, obo ); 1010 1011 } 1012 1013 1014 1015 1016 1017 static isrange( x, y, ax, ay ) 1018 int x, y, ax, ay; 1019 { 1020 register int dx, dy, t; 1021 1022 dy = abs( y - ay ); 1023 dy += dy >> 1; 1024 if ( ( ( dx = abs( x - ax ) ) > 100 ) || ( dy > 100 ) ) 1025 return ( -1 ); 1026 1027 if ( dx < dy ) { 1028 t = dx; 1029 dx = dy; 1030 dy = t; 1031 } 1032 1033 return( ( ( 7 * dx ) + ( dy << 2 ) ) >> 3 ); 1034 } 1035 1036 1037 1038 initbomb( obop ) 1039 OBJECTS *obop; 1040 { 1041 register OBJECTS *ob, *obo; 1042 int angle; 1043 1044 obo = obop; 1045 if ( ( ( !compplane) && ( !obo->ob_bombs ) ) || ( obo->ob_bdelay ) ) 1046 return; 1047 if ( !( ob = allocobj() ) ) 1048 return; 1049 1050 if ( playmode != NOVICE ) 1051 --obo->ob_bombs; 1052 1053 obo->ob_bdelay = 10; 1054 1055 ob->ob_type = BOMB; 1056 ob->ob_state = FALLING; 1057 ob->ob_dx = obo->ob_dx; 1058 ob->ob_dy = obo->ob_dy; 1059 1060 if ( obo->ob_orient ) 1061 angle = ( obo->ob_angle + ( ANGLES / 4 ) ) % ANGLES; 1062 else 1063 angle = ( obo->ob_angle + ( 3 * ANGLES / 4 ) ) % ANGLES; 1064 ob->ob_x = obo->ob_x + ( ( COS( angle ) * 10 ) >> 8 ) + 4; 1065 ob->ob_y = obo->ob_y + ( ( SIN( angle ) * 10 ) >> 8 ) - 4; 1066 ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0; 1067 1068 ob->ob_life = BOMBLIFE; 1069 ob->ob_owner = obo; 1070 ob->ob_clr = obo->ob_clr; 1071 ob->ob_symhgt = ob->ob_symwdt = 8; 1072 ob->ob_drawf = dispbomb; 1073 ob->ob_movef = movebomb; 1074 1075 insertx( ob, obo ); 1076 1077 } 1078 1079 1080 1081 initmiss( obop ) 1082 OBJECTS *obop; 1083 { 1084 register OBJECTS *ob, *obo; 1085 int angle, nspeed; 1086 1087 obo = obop; 1088 if ( obo->ob_mdelay || ( !obo->ob_missiles ) || !missok ) 1089 return; 1090 if ( !( ob = allocobj() ) ) 1091 return; 1092 1093 if ( playmode != NOVICE ) 1094 --obo->ob_missiles; 1095 1096 obo->ob_mdelay = 5; 1097 1098 ob->ob_type = MISSILE; 1099 ob->ob_state = FLYING; 1100 1101 angle = ob->ob_angle = obo->ob_angle; 1102 ob->ob_x = obo->ob_x + ( COS( angle ) >> 4 ) + 4; 1103 ob->ob_y = obo->ob_y + ( SIN( angle ) >> 4 ) - 4; 1104 ob->ob_lx = ob->ob_ly = 0; 1105 ob->ob_speed = nspeed = gmaxspeed + ( gmaxspeed >> 1 ); 1106 setdxdy( ob, nspeed * COS( angle ), nspeed * SIN( angle ) ); 1107 1108 ob->ob_life = MISSLIFE; 1109 ob->ob_owner = obo; 1110 ob->ob_clr = obo->ob_clr; 1111 ob->ob_symhgt = ob->ob_symwdt = 8; 1112 ob->ob_drawf = dispmiss; 1113 ob->ob_movef = movemiss; 1114 ob->ob_target = obo->ob_mfiring; 1115 ob->ob_orient = ob->ob_accel = ob->ob_flaps = 0; 1116 1117 insertx( ob, obo ); 1118 1119 } 1120 1121 1122 1123 initburst( obop ) 1124 OBJECTS *obop; 1125 { 1126 register OBJECTS *ob, *obo; 1127 int angle; 1128 1129 obo = obop; 1130 if ( obo->ob_bsdelay || ( !obo->ob_bursts ) || !missok ) 1131 return; 1132 if ( !( ob = allocobj() ) ) 1133 return; 1134 1135 ob->ob_bsdelay = 5; 1136 1137 if ( playmode != NOVICE ) 1138 --obo->ob_bursts; 1139 1140 ob->ob_type = STARBURST; 1141 ob->ob_state = FALLING; 1142 1143 if ( obo->ob_orient ) 1144 angle = ( obo->ob_angle + ( 3 * ANGLES / 8 ) ) % ANGLES; 1145 else 1146 angle = ( obo->ob_angle + ( 5 * ANGLES / 8 ) ) % ANGLES; 1147 setdxdy( ob, gminspeed * COS( angle ), gminspeed * SIN( angle ) ); 1148 ob->ob_dx += obo->ob_dx; 1149 ob->ob_dy += obo->ob_dy; 1150 1151 ob->ob_x = obo->ob_x + ( ( COS( angle ) * 10 ) >> 10 ) + 4; 1152 ob->ob_y = obo->ob_y + ( ( SIN( angle ) * 10 ) >> 10 ) - 4; 1153 ob->ob_lx = ob->ob_ly = 0; 1154 1155 ob->ob_life = BURSTLIFE; 1156 ob->ob_owner = obo; 1157 ob->ob_clr = obo->ob_clr; 1158 ob->ob_symhgt = ob->ob_symwdt = 8; 1159 ob->ob_drawf = dispburst; 1160 ob->ob_movef = moveburst; 1161 1162 insertx( ob, obo ); 1163 1164 } 1165 1166 1167 1168 static inittarg() 1169 { 1170 register OBJECTS *ob; 1171 register int x, i; 1172 int *tx, *tt; 1173 int minh, maxh, aveh, minx, maxx; 1174 1175 tx = currgame->gm_xtarg; 1176 tt = currgame->gm_ttarg; 1177 1178 if ( ( ( playmode != MULTIPLE ) && ( playmode != ASYNCH ) ) 1179 || ( multbuff->mu_maxplyr == 1 ) ) { 1180 numtarg[0] = 0; 1181 numtarg[1] = MAX_TARG - 3; 1182 } else 1183 numtarg[0] = numtarg[1] = MAX_TARG / 2; 1184 1185 for ( i = 0; i < MAX_TARG; ++i, ++tx, ++tt ) { 1186 targets[i] = ob = allocobj(); 1187 minx = ob->ob_x = *tx; 1188 maxx = ob->ob_x + 15; 1189 minh = 999; 1190 maxh = 0; 1191 for ( x = minx; x <= maxx; ++x ) { 1192 if ( ground[x] > maxh ) 1193 maxh = ground[x]; 1194 if ( ground[x] < minh ) 1195 minh = ground[x]; 1196 } 1197 aveh = ( minh + maxh ) >> 1; 1198 1199 while ( ( ob->ob_y = aveh + 16 ) >= MAX_Y ) 1200 --aveh; 1201 1202 for ( x = minx; x <= maxx; ++x ) 1203 ground[x] = aveh; 1204 1205 ob->ob_dx = ob->ob_dy = ob->ob_lx = ob->ob_ly = ob->ob_ldx 1206 = ob->ob_ldy = ob->ob_angle = ob->ob_hitcount = 0; 1207 ob->ob_type = TARGET; 1208 ob->ob_state = STANDING; 1209 ob->ob_orient = *tt; 1210 ob->ob_life = i; 1211 1212 if ( ( ( playmode != MULTIPLE ) && ( playmode != ASYNCH ) ) 1213 || ( multbuff->mu_maxplyr == 1 ) ) 1214 ob->ob_owner = &nobjects[( ( i < MAX_TARG / 2 ) 1215 && ( i > MAX_TARG /2 - 4 ) ) 1216 ? 0 : 1 ]; 1217 else 1218 ob->ob_owner = &nobjects[i >= ( MAX_TARG / 2 ) ]; 1219 ob->ob_clr = ob->ob_owner->ob_clr; 1220 ob->ob_symhgt = ob->ob_symwdt = 16; 1221 ob->ob_drawf = disptarg; 1222 ob->ob_movef = movetarg; 1223 1224 insertx( ob, &topobj ); 1225 } 1226 } 1227 1228 1229 1230 initexpl( obop, small ) 1231 OBJECTS *obop; 1232 int small; 1233 { 1234 register OBJECTS *ob, *obo; 1235 int i, ic, life, speed; 1236 int obox, oboy, obodx, obody, oboclr, obotype; 1237 BOOL mansym; 1238 int orient; 1239 1240 1241 obo = obop; 1242 obox = obo->ob_x + ( obo->ob_symwdt >> 1 ); 1243 oboy = obo->ob_y + ( obo->ob_symhgt >> 1 ); 1244 obodx = obo->ob_dx >> 2; 1245 obody = obo->ob_dy >> 2; 1246 oboclr = obo->ob_clr; 1247 1248 if ( ( ( obotype = obo->ob_type ) == TARGET ) 1249 && ( obo->ob_orient == 2 ) ) { 1250 ic = 1; 1251 speed = gminspeed; 1252 } else { 1253 ic = small ? 6 : 2; 1254 speed = gminspeed >> ( ( explseed & 7 ) != 7 ); 1255 } 1256 mansym = ( obotype == PLANE ) && ( ( obo->ob_state == FLYING ) 1257 || ( obo->ob_state == WOUNDED ) ); 1258 1259 for ( i = 1; i <= 15; i += ic ) { 1260 if ( !( ob = allocobj() ) ) 1261 return; 1262 1263 ob->ob_type = EXPLOSION; 1264 1265 setdxdy( ob, COS( i ) * speed, SIN( i ) * speed ); 1266 ob->ob_dx += obodx; 1267 ob->ob_dy += obody; 1268 1269 if ( !( explseed = ( ob->ob_x = obox + ob->ob_dx ) 1270 * ( ob->ob_y = oboy + ob->ob_dy ) 1271 * explseed + 7491 ) ) 1272 explseed = 74917777; 1273 1274 ob->ob_life = EXPLLIFE; 1275 orient = ob->ob_orient = ( explseed & 0x01C0 ) >> 6; 1276 if ( mansym && ( ( !orient ) || ( orient == 7 ) ) ) { 1277 mansym = orient = ob->ob_orient = 0; 1278 ob->ob_dx = obodx; 1279 ob->ob_dy = -gminspeed; 1280 } 1281 1282 ob->ob_lx = ob->ob_ly = ob->ob_hitcount = ob->ob_speed = 0; 1283 ob->ob_owner = obo; 1284 ob->ob_clr = oboclr; 1285 ob->ob_symhgt = ob->ob_symwdt = 8; 1286 ob->ob_drawf = dispexpl; 1287 ob->ob_movef = moveexpl; 1288 1289 if ( orient ) 1290 initsound( ob, S_EXPLOSION ); 1291 1292 insertx( ob, obo ); 1293 } 1294 } 1295 1296 1297 1298 initsmok( obop ) 1299 OBJECTS *obop; 1300 { 1301 register OBJECTS *ob, *obo; 1302 1303 1304 if ( !( ob = allocobj() ) ) 1305 return; 1306 1307 ob->ob_type = SMOKE; 1308 1309 ob->ob_x = ( obo = obop )->ob_x + 8; 1310 ob->ob_y = obo->ob_y - 8; 1311 ob->ob_dx = obo->ob_dx; 1312 ob->ob_dy = obo->ob_dy; 1313 ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0; 1314 ob->ob_life = SMOKELIFE; 1315 ob->ob_owner = obo; 1316 ob->ob_symhgt = ob->ob_symwdt = 1; 1317 ob->ob_drawf = NULL; 1318 ob->ob_movef = movesmok; 1319 ob->ob_clr = obo->ob_clr; 1320 } 1321 1322 1323 1324 1325 static ifx[] = { MINFLCKX, MINFLCKX + 1000, MAXFLCKX - 1000, MAXFLCKX }; 1326 static ify[] = { MAX_Y-1, MAX_Y-1, MAX_Y-1, MAX_Y-1 }; 1327 static ifdx[] = { 2, 2, -2, -2 }; 1328 1329 1330 1331 initflck() 1332 { 1333 register OBJECTS *ob; 1334 register int i, j; 1335 1336 if ( playmode == NOVICE ) 1337 return; 1338 1339 for ( i = 0; i < MAX_FLCK; ++i ) { 1340 1341 if ( !( ob = allocobj() ) ) 1342 return; 1343 1344 ob->ob_type = FLOCK; 1345 ob->ob_state = FLYING; 1346 ob->ob_x = ifx[i]; 1347 ob->ob_y = ify[i]; 1348 ob->ob_dx = ifdx[i]; 1349 ob->ob_dy = ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0; 1350 ob->ob_orient = 0; 1351 ob->ob_life = FLOCKLIFE; 1352 ob->ob_owner = ob; 1353 ob->ob_symhgt = ob->ob_symwdt = 16; 1354 ob->ob_drawf = dispflck; 1355 ob->ob_movef = moveflck; 1356 ob->ob_clr = 9; 1357 insertx( ob, &topobj ); 1358 for ( j = 0; j < MAX_BIRD; ++j ) 1359 initbird( ob, 1 ); 1360 } 1361 } 1362 1363 1364 1365 initbird( obop, i ) 1366 OBJECTS *obop; 1367 int i; 1368 { 1369 register OBJECTS *ob, *obo; 1370 static ibx[] = { 8, 3, 0, 6, 7, 14, 10, 12 }; 1371 static iby[] = { 16, 1, 8, 3, 12, 10, 7, 14 }; 1372 static ibdx[] = { -2, 2, -3, 3, -1, 1, 0, 0 }; 1373 static ibdy[] = { -1, -2, -1, -2, -1, -2, -1, -2 }; 1374 1375 1376 if ( !( ob = allocobj() ) ) 1377 return; 1378 1379 ob->ob_type = BIRD; 1380 1381 ob->ob_x = ( obo = obop )->ob_x + ibx[i]; 1382 ob->ob_y = obo->ob_y - iby[i]; 1383 ob->ob_dx = ibdx[i]; 1384 ob->ob_dy = ibdy[i]; 1385 ob->ob_orient = ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0; 1386 ob->ob_life = BIRDLIFE; 1387 ob->ob_owner = obo; 1388 ob->ob_symhgt = 2; 1389 ob->ob_symwdt = 4; 1390 ob->ob_drawf = dispbird; 1391 ob->ob_movef = movebird; 1392 ob->ob_clr = obo->ob_clr; 1393 insertx( ob, obo ); 1394 } 1395 1396 1397 1398 initoxen() 1399 { 1400 register OBJECTS *ob; 1401 register int i; 1402 static iox[] = { 1376, 1608 }; 1403 static ioy[] = { 80, 91 }; 1404 1405 if ( playmode == NOVICE ) { 1406 for ( i = 0; i < MAX_OXEN; ++i ) 1407 targets[MAX_TARG + i] = NULL; 1408 return; 1409 } 1410 1411 for ( i = 0; i < MAX_OXEN; ++i ) { 1412 if ( !( targets[MAX_TARG + i] = ob = allocobj() ) ) 1413 return; 1414 1415 ob->ob_type = OX; 1416 ob->ob_state = STANDING; 1417 ob->ob_x = iox[i]; 1418 ob->ob_y = ioy[i]; 1419 ob->ob_orient = ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy 1420 = ob->ob_dx = ob->ob_dy = 0; 1421 ob->ob_owner = ob; 1422 ob->ob_symhgt = 16; 1423 ob->ob_symwdt = 16; 1424 ob->ob_drawf = NULL; 1425 ob->ob_movef = moveox; 1426 ob->ob_clr = 1; 1427 insertx( ob, &topobj ); 1428 } 1429 } 1430 ÿ