home *** CD-ROM | disk | FTP | other *** search
/ Crazy Collection 9 / CC-09.iso / GAMES_9 / ZOOP / DATA.A00 / ZOOP.OLD < prev    next >
Encoding:
Text File  |  1995-08-25  |  142.0 KB  |  6,544 lines

  1. /*
  2.       HOOKSTONE
  3.  
  4.       PROJECT    : Zoop
  5.       MODULE     : Main
  6.       AUTHOR     : J.Johnson  Advanced Visual Productions
  7.  
  8.       <Notes>
  9.  
  10.     Inertia for dial.
  11.  
  12.     Antialias edges for title screens.
  13.  
  14.     Bugs as per viacom bug report.
  15.  
  16.       <Bugs>
  17.  
  18.     Managed to get a WIN when escape pressed.
  19.  
  20.     When everybody dies and you start again, the level & blocks are wrong.
  21.  
  22.     Perhaps I need to flush messages.
  23.  
  24.     When a players dies, his name can still be seen at bottom of other screens.
  25.  
  26.     More than one person could win.
  27.  
  28.     Some workstations are not seeing other players.
  29.  
  30.     Does not seem to addnodes/deletenodes correctly. New players join but possibly
  31.     at list position >4 so they dont actually get seen on some workstations.
  32.  
  33. */
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <conio.h>
  38. #include <string.h>
  39. #include <i86.h>
  40. #include <time.h>
  41. #include <graph.h>
  42.  
  43. #include "xtypes.h"
  44. #include "drivers.hpp"
  45. #include "svga.hpp"
  46. #include "pcx.hpp"
  47. #include "gfxcomp8.hpp"
  48. #include "keydefs.hpp"
  49.  
  50. //Univbe
  51. #include "uvbelib.h"
  52.  
  53. // Sound library
  54. #include "ail.h"
  55. #include "sound.hpp"
  56.  
  57. //Network library
  58. #include "zoopnet.hpp"
  59.  
  60. //===========================================================================
  61. // Definitions
  62. //===========================================================================
  63.  
  64. #define MAXLEVELS  10
  65.  
  66. #define MAPWIDTH   40
  67. #define MAPHEIGHT  30
  68. #define MAPSIZE    MAPWIDTH*MAPHEIGHT
  69.  
  70. // NUMSPRITES is max sprites - (4*5)*2 vert (8*4)*2 horz
  71. // +1 for main man +1 for enemy win if full +32 for fx
  72. // +6 for score +5 for bonus +4 for kills +24 for net
  73. #define NUMSPRITES 200
  74.  
  75. // Player I/O Control
  76.  
  77. #define CONTROL_JOYSTICK    0
  78. #define CONTROL_MOUSE        1
  79. #define CONTROL_KEYBOARD    2
  80.  
  81. #define MOUSE_BUTTON_RIGHT    0xffff-1
  82. #define MOUSE_BUTTON_LEFT     0xffff-2
  83.  
  84. // Player modes
  85.  
  86. #define INMIDDLE  0
  87. #define RUNTO     1
  88. #define RUNFROM   2
  89.  
  90. #define FACEUP    0
  91. #define FACEDOWN  1
  92. #define FACELEFT  2
  93. #define FACERIGHT 3
  94.  
  95. #define FIRESTEP  32
  96.  
  97. // Animation defines
  98.  
  99. #define ADOWN          0
  100. #define ARIGHT          1
  101. #define AUP              2
  102. #define ALEFT     3
  103. #define AWDOWN    4
  104. #define AWRIGHT   5
  105. #define AWUP      6
  106. #define AWLEFT    7
  107.  
  108. // Quadrant id's
  109.  
  110. #define QUADTOP   1
  111. #define QUADBOT   2
  112. #define QUADLEFT  3
  113. #define QUADRIGHT 4
  114.  
  115. #define NUMLINES  16
  116.  
  117. // Game Type
  118. #define CONTINUE    0
  119. #define LEVELPLAY    1
  120. #define MULTI        2
  121.  
  122. // Holdback time for full line
  123.  
  124. #define HOLDBACKTIME        (24*16)
  125.  
  126. // Network
  127.  
  128. #define NET_Back_Color            237
  129.  
  130. //===========================================================================
  131. // External declarations
  132. //===========================================================================
  133.  
  134. extern "C" {
  135.     void BlitComp8Sprite32x32(UBYTE *,UBYTE *);
  136.     void BlitComp8SSprite32x32(UBYTE *,UBYTE *);
  137. };
  138.  
  139. //===========================================================================
  140. // Structure definitions
  141. //===========================================================================
  142.  
  143. struct TUPDATE
  144. {
  145.     UWORD                 x, y;
  146.     UDWORD                 offset;
  147.     UDWORD                 bank1, bank2;
  148.     UBYTE                 *start1, *start2;
  149.     UWORD                 phase;
  150.     UBYTE                 *buftop1, *bufbot1;
  151.     UBYTE                 *buftop2, *bufbot2;
  152.     UWORD                 lines1, lines2;
  153.     BOOL                  update1, update2;
  154. };
  155.  
  156. //---------------------------------------------------------------------------
  157. // Include Zoop sprite structure and frame definitions
  158. //---------------------------------------------------------------------------
  159.  
  160. #include "zoopspr.h"
  161.  
  162. //===========================================================================
  163. // Level definition
  164. //===========================================================================
  165.  
  166. #define BMNONE    0
  167. #define BM1            1
  168. #define BM2            2
  169. #define BM3            4
  170.  
  171. //---------------------------------------------------------------------------
  172.  
  173. struct LEVEL
  174. {
  175.     DWORD                 Speed;
  176.     WORD                  ColorThreshold;
  177.     WORD                  Kills;
  178.     UBYTE                 WhichBombs;
  179.     WORD                  Bombs;
  180.     UWORD                 BonusRand;
  181.     BYTE                  BackImage[12];
  182.     UWORD                 StrobeColor1;
  183.     UWORD                 StrobeColor2;
  184. };
  185.  
  186. //---------------------------------------------------------------------------
  187.  
  188. LEVEL LevelCon[MAXLEVELS] = {
  189. /*   Spd   ColTh Kills  Bombs             BombNo Bonus  Image               Strb1    Strb2
  190.     ------ ------ ----- ------------------ ------ -----  ------------------  -------  ----- */
  191.     { 45,        35,    20,    BMNONE,                0,     10,         "scr1.imx",             112,         112  } ,
  192.     { 40,        35,    50,    BMNONE,                0,     12,         "scr2.imx",             113,         113  } ,
  193.     { 35,        35,    90,    BM1,                   2,        12,         "scr3.imx",             114,         114  } ,
  194.     { 30,        35,    100,    BM2,                   2,        14,         "scr4.imx",             115,         115  } ,
  195.     { 25,        35,    110,    BM3,                   2,        14,         "scr5.imx",             116,         116  } ,
  196.     { 20,        35,    120,    BM1+BM2,               2,        16,         "scr6.imx",             117,         117  } ,
  197.     { 17,        35,    110,    BM2+BM3,               2,        16,         "scr7.imx",             118,         118  } ,
  198.     { 14,        35,    90,    BM1+BM2+BM3,       2,        18,         "scr8.imx",             119,         120  } ,
  199.     { 11,        35,    80,    BM1+BM2+BM3,        3,        18,         "scr9.imx",             254,         254  } ,
  200.     { 4,        35,    70,    BM1+BM2+BM3,        3,        20,         "scr10.imx",         254,         254  }
  201. };
  202.  
  203. UWORD DifficultyCon[5] = { 0, 30, 39, 47, 53 };
  204.  
  205. //---------------------------------------------------------------------------
  206.  
  207. LEVEL LevelLev[MAXLEVELS] = {
  208. /*   Spd   ColTh Kills  Bombs             BombNo Bonus  Image               Strb1    Strb2
  209.     ------ ------ ----- ------------------ ------ -----  ------------------  -------  ----- */
  210.     { 45,        35,    20,    BMNONE,                0,     10,         "scr1.imx",             112,         112  } ,
  211.     { 40,        35,    50,    BMNONE,                0,     12,         "scr2.imx",             113,         113  } ,
  212.     { 35,        35,    90,    BM1,                   2,        12,         "scr3.imx",             114,         114  } ,
  213.     { 30,        35,    100,    BM2,                   2,        14,         "scr4.imx",             115,         115  } ,
  214.     { 25,        35,    110,    BM3,                   2,        14,         "scr5.imx",             116,         116  } ,
  215.     { 20,        35,    120,    BM1+BM2,               2,        16,         "scr6.imx",             117,         117  } ,
  216.     { 17,        35,    140,    BM2+BM3,               2,        16,         "scr7.imx",             118,         118  } ,
  217.     { 14,        35,    160,    BM1+BM2+BM3,       2,        18,         "scr8.imx",             119,         120  } ,
  218.     { 11,        35,    180,    BM1+BM2+BM3,        3,        18,         "scr9.imx",             254,         254  } ,
  219.     { 10,        35,    200,    BM1+BM2+BM3,        3,        20,         "scr10.imx",         254,         254  }
  220. };
  221.  
  222. UWORD DifficultyLev[5] = { 0, 14, 20, 25, 30 };
  223.  
  224. //---------------------------------------------------------------------------
  225.  
  226. LEVEL LevelNet[MAXLEVELS] = {
  227. /*   Spd   ColTh Kills  Bombs             BombNo Bonus  Image               Strb1    Strb2
  228.     ------ ------ ----- ------------------ ------ -----  ------------------  -------  ----- */
  229.     { 45,        35,    20,    BMNONE,                0,     50,         "scr1.imx",             112,         112  } ,
  230.     { 40,        35,    50,    BMNONE,                0,     52,         "scr2.imx",             113,         113  } ,
  231.     { 35,        35,    90,    BM1,                   2,        52,         "scr3.imx",             114,         114  } ,
  232.     { 30,        35,    100,    BM2,                   2,        54,         "scr4.imx",             115,         115  } ,
  233.     { 25,        35,    110,    BM3,                   2,        54,         "scr5.imx",             116,         116  } ,
  234.     { 20,        35,    120,    BM1+BM2,               2,        56,         "scr6.imx",             117,         117  } ,
  235.     { 17,        35,    110,    BM2+BM3,               2,        56,         "scr7.imx",             118,         118  } ,
  236.     { 14,        35,    90,    BM1+BM2+BM3,       2,        60,         "scr8.imx",             119,         120  } ,
  237.     { 11,        35,    80,    BM1+BM2+BM3,        3,        60,         "scr9.imx",             254,         254  } ,
  238.     { 4,        35,    70,    BM1+BM2+BM3,        3,        70,         "scr10.imx",         254,         254  }
  239. };
  240.  
  241. UWORD DifficultyNet[5] = { 0, 30, 39, 47, 53 };
  242.  
  243. //---------------------------------------------------------------------------
  244.  
  245. LEVEL *LevelSet;
  246. UWORD *DifficultySet;
  247.  
  248. //===========================================================================
  249. // Line definition
  250. //===========================================================================
  251.  
  252. struct LINE
  253. {
  254.     UWORD                 backcolor;        //color of last sprite in line
  255.     UWORD                 count;         //count of sprites on line
  256.     UWORD                 killcount;     //count of killer sprites on line
  257.     UWORD                 wait;          //wait value for line
  258.     UWORD                 quad;          //line quad
  259. };
  260.  
  261. //===========================================================================
  262. // Dpmi memory info
  263. //===========================================================================
  264.  
  265. struct meminfo
  266. {
  267.   DWORD                     LargestBlockAvail;
  268.   DWORD                     MaxUnlockedPage;
  269.   DWORD                     LargestLockablePage;
  270.   DWORD                     LinAddrSpace;
  271.   DWORD                     NumFreePagesAvail;
  272.   DWORD                     NumPhysicalPagesFree;
  273.   DWORD                     TotalPhysicalPages;
  274.   DWORD                     FreeLinAddrSpace;
  275.   DWORD                     SizeOfPageFile;
  276.   DWORD                     Reserved[3];
  277. } MemInfo;
  278.  
  279. #define DPMI_INT  0x31
  280.  
  281. //===========================================================================
  282. // Object/Structure instances & real machine variable declaration
  283. //===========================================================================
  284.  
  285. JOYSTICK Joy;
  286. UDWORD JoyNormalx,JoyNormaly;
  287.  
  288. PCXIMAGE BackPcx;
  289. PCXIMAGE GOverPcx;
  290.  
  291. SPRITE GSprite[NUMSPRITES];
  292.  
  293. GFX GFXCas;
  294.  
  295. LINE GLine[NUMLINES];
  296. BOOL DangerLine[NUMLINES];
  297. WORD GLastQuad;
  298.  
  299. // Graphic image and animation
  300.  
  301. OBJECT *GOBJ;
  302. UWORD  *GFRM;
  303. UBYTE  **GDAT;
  304. ANIM   **GANM;
  305.  
  306. UWORD Score[7];
  307. UWORD Digit[7],ODigit[7];
  308. UWORD SKill[4];
  309. UWORD KDigit[4],KODigit[4];
  310. UWORD SLevel[2];
  311. UWORD LDigit[2],LODigit[2];
  312.  
  313. // Game control
  314.  
  315. UDWORD AuxInput;
  316.  
  317. UBYTE Key_Down;
  318. UBYTE Key_Up;
  319. UBYTE Key_Left;
  320. UBYTE Key_Right;
  321. UBYTE Key_Fire;
  322. UBYTE Key_Pause;
  323.  
  324. // Alter TimeSpeed and GColorThreshold to increase difficulty
  325.  
  326. UWORD BonusRand;
  327. WORD  BonusCount;
  328. WORD  SpringFull;
  329. UWORD Spring[6];
  330. UWORD SpringMerge[6];
  331.  
  332. BYTE HiTime[8];
  333.  
  334. UWORD GColorThreshold;
  335. DWORD TimeSpeed;
  336. WORD  PlayerSpeed,PlayerMoveBy;
  337. UWORD GPlayerMode,GPlayerFacing;
  338. WORD  GPlayerRunLine;
  339. UWORD GStartRunx,GStartRuny,LastLineKill;
  340. UDWORD GScore,GBScore,Accum;
  341. WORD  WalkLine,LastKill,NumBombs,LastBombQuad,LastBombKill;
  342. BOOL  BombTwoFired;
  343. UWORD FireWait;
  344. BOOL  FireEnableStatus;
  345. BOOL  GGameOver;
  346. BOOL    DoingLeadIn;
  347.  
  348. UBYTE GPalette[768];
  349. UBYTE APalette[768];
  350. UBYTE WPalette[768];
  351. UBYTE TPalette[768];
  352.  
  353. #define BEING_BUILT    0
  354. #define BUILT            1
  355. #define WILL_KILL        2
  356. DWORD LineState;
  357.  
  358. WORD  Level,OldLevel,Kills,LevelBombs;
  359. WORD  EnemyLeadIn;
  360. WORD  GameMode;
  361. UDWORD TotalKills,GBKills;
  362. UBYTE WhichBombs;
  363. BOOL DoBeam;
  364. BOOL Strobe;
  365. BYTE StrobeVal1,StrobeVal2,StrobeColor1,StrobeColor2;
  366. BYTE StrobeR1,StrobeR2;
  367. BYTE StrobeG1,StrobeG2;
  368. BYTE StrobeB1,StrobeB2;
  369. WORD StrobeSound;
  370. BOOL Bomb2Sound;
  371.  
  372. UWORD DetailLevel;
  373.  
  374. WORD NEWxpos,NEWypos;
  375. WORD NEWrquad,NEWquadline;
  376. WORD NEWrcolor,NEWspr;
  377.  
  378. WORD MOVquadline;
  379. WORD MOVmx,MOVmy;
  380. WORD MOVcx,MOVcy;
  381. WORD MOVanm;
  382.  
  383. WORD AppearCount,HoldBack,HoldLine;
  384.  
  385. TUPDATE MAPUpdate[MAPSIZE+MAPWIDTH];
  386.  
  387. UBYTE buf1[307200];  //graphic update buffer
  388. UBYTE buf2[307200];  //background buffer
  389. UBYTE buf3[307200];  //transition buffer
  390.  
  391. UWORD bankstart[5];
  392. UDWORD Yoffset[480];
  393. UDWORD Moffset[MAPHEIGHT];
  394.  
  395. SVGA Svga;
  396.  
  397. //===========================================================================
  398. // Network
  399. //===========================================================================
  400.  
  401. BOOL  NET_Installed;
  402. DWORD NET_Game;
  403.  
  404. BYTE  NET_Name_Letter[20];
  405. DWORD NET_Name_Sprite[20];
  406. DWORD NET_Name_Posx[20];
  407.  
  408. BOOL    NET_Logged_In;
  409.  
  410. //===========================================================================
  411. // Event variables
  412. //===========================================================================
  413.  
  414. // AddBlocks event
  415.  
  416. DWORD EVENT_AddBlock;
  417. DWORD BlockAddAmount, BlockAddColor;
  418.  
  419. //---------------------------------------------------------------------------
  420.  
  421. // Bonus event
  422.  
  423. DWORD EVENT_Bonus;
  424. DWORD EVENT_BlowUp;
  425.  
  426. //---------------------------------------------------------------------------
  427.  
  428. // Speedup event
  429.  
  430. DWORD EVENT_SpeedUp;
  431. DWORD SpeedUpDuration, OldSpeed;
  432.  
  433. //---------------------------------------------------------------------------
  434.  
  435. BOOL EVENT_AddTarget;
  436.  
  437. // Pause event
  438.  
  439. BOOL EVENT_Pause;
  440.  
  441. //---------------------------------------------------------------------------
  442. // Weapon send state variables
  443. //---------------------------------------------------------------------------
  444.  
  445. DWORD        NETSEQUENCE;
  446. DWORD        NETSEQUENCECOUNT;
  447. DWORD        NETTARGETTYPE;
  448.  
  449. //===========================================================================
  450. // Globals for setup selections
  451. //===========================================================================
  452.  
  453. UWORD Difficulty;
  454. UWORD LastDifficulty;
  455. WORD LastLevel;
  456.  
  457. //===========================================================================
  458. // DPMI Memory available
  459. //===========================================================================
  460.  
  461. BYTE MemFree[12];
  462.  
  463. void MemAvail()
  464. {
  465.   BYTE bitinfo[30];
  466.   BYTE tmp[10];
  467.  
  468.   union REGS regs;
  469.   struct SREGS sregs;
  470.  
  471.   regs.x.eax = 0x00000500;
  472.   memset( &sregs, 0, sizeof(sregs) );
  473.   sregs.es = FP_SEG( &MemInfo );
  474.   regs.x.edi = FP_OFF( &MemInfo );
  475.  
  476.   int386x( DPMI_INT, ®s, ®s, &sregs );
  477.  
  478.   MemFree[0]=0;
  479.   ltoa(MemInfo.LargestBlockAvail/1024,MemFree,10);
  480.   strcat(MemFree,"K");
  481. }
  482.  
  483. //===========================================================================
  484. // Inline assembler
  485. //===========================================================================
  486.  
  487. extern void BUFBlitTile32x32(UBYTE *,UBYTE *,DWORD);
  488. #pragma aux BUFBlitTile32x32 = \
  489.                                 "            mov ecx,ebx"\
  490.                                 "            mov esi,eax"\
  491.                                 "            mov edi,edx"\
  492.                                 "            jmp dotileblit"\
  493.                                 "dotileblit:"\
  494.                                 "              mov eax,[esi]"\
  495.                                 "            mov [edi],eax"\
  496.                                 "            mov eax,[esi+4]"\
  497.                                 "            mov [edi+4],eax"\
  498.                                 "            mov eax,[esi+8]"\
  499.                                 "            mov [edi+8],eax"\
  500.                                 "            mov eax,[esi+12]"\
  501.                                 "            mov [edi+12],eax"\
  502.                                 "            add esi,640"\
  503.                                 "            add edi,640"\
  504.                                 "            dec ecx"\
  505.                                 "            jnz dotileblit"\
  506. parm caller [eax] [edx] [ebx] modify [eax esi edi ecx];
  507.  
  508. //---------------------------------------------------------------------------
  509.  
  510. // Set palette DAC
  511.  
  512. extern void PalDac(DWORD,DWORD);
  513. #pragma aux PalDac = \
  514.                                 "            mov   ebx, edx"\
  515.                                 "            mov    dx, 03c8h"\
  516.                                 "            out    dx, al"\
  517.                                 "            inc    dx"\
  518.                                 "        mov   eax,ebx"\
  519.                                 "            out    dx, al"\
  520.                                 "            shr   eax, 8"\
  521.                                 "            out    dx, al"\
  522.                                 "            shr   eax, 8"\
  523.                                 "            out    dx, al"\
  524. parm caller [eax] [edx] modify [eax ebx edx];
  525.  
  526. //===========================================================================
  527. // Timer functions
  528. //===========================================================================
  529.  
  530. volatile UDWORD TimerCount;
  531. HTIMER GameTimer;
  532.  
  533. //---------------------------------------------------------------------------
  534.  
  535. void cdecl tfunc(void);
  536.  
  537. void tfunc(void)
  538. {
  539.     TimerCount++;
  540.     if( NET_Player_Count > 0 ) NET_Player_Count--;
  541.     if( AuxInput == CONTROL_JOYSTICK ) JOYRead( Joy );
  542. }
  543.  
  544. //---------------------------------------------------------------------------
  545.  
  546. void TimerSetup()
  547. {
  548.     TimerCount=0;
  549.  
  550.     GameTimer = AIL_register_timer(&tfunc);
  551.  
  552.     AIL_set_timer_frequency(GameTimer,60);
  553.  
  554.     AIL_start_timer(GameTimer);
  555. }
  556.  
  557. //---------------------------------------------------------------------------
  558.  
  559. void TimerKill()
  560. {
  561.     AIL_release_timer_handle(GameTimer);
  562. }
  563.  
  564. //---------------------------------------------------------------------------
  565.  
  566. void WaitTimer()
  567. {
  568.     UDWORD t=TimerCount;
  569.  
  570.     while(TimerCount == t);
  571. }
  572.  
  573. //===========================================================================
  574. // Game play timing functions
  575. //===========================================================================
  576.  
  577. clock_t CurrentTime, PauseTime;
  578. UDWORD GameTick, GameClock;
  579.  
  580. inline UDWORD HZClock()
  581. {
  582.     return( TimerCount );
  583. }
  584.  
  585. //---------------------------------------------------------------------------
  586.  
  587. void StartGameClock()
  588. {
  589.     GameClock = HZClock();
  590. }
  591.  
  592. //---------------------------------------------------------------------------
  593.  
  594. void SetPauseTime()
  595. {
  596.     PauseTime = HZClock();
  597. }
  598.  
  599. //---------------------------------------------------------------------------
  600.  
  601. void ModifyGameClock()
  602. {
  603.      GameClock -= HZClock() - PauseTime;
  604. }
  605.  
  606. //---------------------------------------------------------------------------
  607.  
  608. UDWORD GetGameClock()
  609. {
  610.     CurrentTime = HZClock();
  611.     return( ( CurrentTime + GameClock) / 60 );  // 60 Frames Per Second
  612. }
  613.  
  614. //---------------------------------------------------------------------------
  615.  
  616. void FormatTime( UDWORD time, BYTE *t )
  617. {
  618.     UDWORD hour,min,sec;
  619.     BYTE h[8], m[8], s[8];
  620.  
  621.     hour = time / ( 60 * 60 );
  622.     min  = ( time - (hour * (60*60))) / 60;
  623.     sec  = ( time - (min * 60) - (hour * (60*60)));
  624.  
  625.     itoa( hour, h, 10 );
  626.     itoa( min, m, 10 );
  627.     itoa( sec, s, 10 );
  628.  
  629.     t[0] = h[0];  //Hour
  630.  
  631.     t[1] = ':';
  632.  
  633.     if( strlen( m ) == 1) {  //Min
  634.         t[2] = '0';
  635.         t[3] = m[0];
  636.         }
  637.     else {
  638.         t[2] = m[0];
  639.         t[3] = m[1];
  640.         }
  641.  
  642.     t[4] = ':';
  643.  
  644.     if( strlen( s ) == 1) {  //Sec
  645.         t[5] = '0';
  646.         t[6] = s[0];
  647.         }
  648.     else {
  649.         t[5] = s[0];
  650.         t[6] = s[1];
  651.         }
  652.     t[7] = 0;
  653. }
  654.  
  655. //===========================================================================
  656. // Debug macros
  657. //===========================================================================
  658.  
  659. #define DEBUG_INIT                { FILE *debugfile = fopen( "debug.txt", "a+t" ); }
  660.  
  661. #define DEBUG( a,b )                { fprintf( debugfile, a, b ); }
  662.  
  663. #define DEBUG_CLOSE( a,b )        { fclose( debugfile ); }
  664.  
  665. //===========================================================================
  666. // Palette functions
  667. //===========================================================================
  668.  
  669. void SPal(BYTE i,BYTE r,BYTE g,BYTE b)
  670. {
  671.     PalDac(i, (b << 16) + (g << 8) + r);
  672.     GPalette[i*3]=r;
  673.     GPalette[(i*3)+1]=g;
  674.     GPalette[(i*3)+2]=b;
  675. }
  676.  
  677. //---------------------------------------------------------------------------
  678.  
  679. void BlackPal()
  680. {
  681.     for(UWORD i=0; i<256; i++) {
  682.         PalDac(i, 0);
  683.         }
  684.     for(i=0; i<256; i++) {
  685.         GPalette[i*3]=0;
  686.         GPalette[(i*3)+1]=0;
  687.         GPalette[(i*3)+2]=0;
  688.         }
  689. }
  690.  
  691. //---------------------------------------------------------------------------
  692.  
  693. void SetPal(UBYTE *palette)
  694. {
  695.     UWORD pd=0;
  696.     UBYTE *p,*g;
  697.  
  698.     g=GPalette;
  699.     p=palette;
  700.     pd=0;
  701.     for(UWORD i=0;i<768;i+=3) {
  702.         while((inp(0x03da) & 1)!=1); //wait for horizontal blank
  703.         PalDac(pd, (*(p+2) << 16) + (*(p+1) << 8) + *p);
  704.         pd++;
  705.         p+=3; g+=3;
  706.         }
  707.     for(i=0;i<768;i+=3) {
  708.         GPalette[i]=palette[i];
  709.         GPalette[i+1]=palette[i+1];
  710.         GPalette[i+2]=palette[i+2];
  711.         }
  712. }
  713.  
  714. //---------------------------------------------------------------------------
  715.  
  716. void SetForFadeOut(UWORD fadefrom,UWORD fadeto)
  717. {
  718.     for(UWORD i=fadefrom*3;i<fadeto*3;i+=3) {
  719.         APalette[i]=0;
  720.         APalette[i+1]=0;
  721.         APalette[i+2]=0;
  722.         }
  723. }
  724.  
  725. //---------------------------------------------------------------------------
  726.  
  727. void CopyPal(UBYTE *palf,UBYTE *palt,UWORD f,UWORD t,UWORD s)
  728. {
  729.     UWORD pf=f*3,pt=t*3;
  730.  
  731.     for(UWORD i=0;i<s;i++) {
  732.         palt[pt]=palf[pf];
  733.         palt[pt+1]=palf[pf+1];
  734.         palt[pt+2]=palf[pf+2];
  735.         pt+=3; pf+=3;
  736.         }
  737. }
  738.  
  739. //---------------------------------------------------------------------------
  740.  
  741. void FillPal( UBYTE *fp, UBYTE *tp, UWORD f, UWORD t, UWORD s )
  742. {
  743.     UWORD i;
  744.  
  745.     f *= 3;
  746.     t *= 3;
  747.     s *= 3;
  748.  
  749.     for( i=f; i<t; i+=3 ) {
  750.         tp[i] = fp[s];
  751.         tp[i+1] = fp[s+1];
  752.         tp[i+2] = fp[s+2];
  753.         }
  754. }
  755.  
  756. //---------------------------------------------------------------------------
  757.  
  758. void SetPalSeg(UBYTE *pal,UWORD f,UWORD t)
  759. {
  760.     UWORD pf, pt=t*3;
  761.  
  762.     for(pf=f*3; pf<pt; pf+=3) {
  763.         while((inp(0x03da) & 1)!=1); //wait for horizontal blank
  764.         PalDac(pf/3, (pal[pf+2] << 16) + (pal[pf+1] << 8) + pal[pf]);
  765.         GPalette[pf] = pal[pf];
  766.         GPalette[pf+1] = pal[pf+1];
  767.         GPalette[pf+2] = pal[pf+2];
  768.         }
  769. }
  770.  
  771. //---------------------------------------------------------------------------
  772.  
  773. BOOL MorphPalStep(UBYTE st,UBYTE en,UWORD speed,UBYTE *palette)
  774. {
  775.     UWORD p=0;
  776.     WORD pval,pcmp;
  777.     BOOL done=FALSE,change=FALSE;
  778.  
  779.     done=TRUE;
  780.     for(UWORD i=0;i<768;i+=3) {
  781.         if((i>=st*3) && (i<=en*3)) {
  782.             change=FALSE;
  783.             for(UWORD sp=i;sp<i+3;sp++) {
  784.                  if(GPalette[sp] != palette[sp]) {
  785.                     pval=GPalette[sp];
  786.                     pcmp=palette[sp];
  787.                     if(pval < pcmp) {
  788.                         pval+=speed;
  789.                         if(pval > pcmp) pval=pcmp;
  790.                         }
  791.                      else {
  792.                         pval-=speed;
  793.                         if(pval < pcmp) pval=pcmp;
  794.                         }
  795.                     GPalette[sp]=pval;
  796.                     done=FALSE;
  797.                     change=TRUE;
  798.                      }
  799.                  }
  800.             if(change) {
  801.                 while((inp(0x03da) & 1)!=1); //wait for horizontal blank
  802.                 PalDac(p, (GPalette[i+2] << 16) + (GPalette[i+1] << 8) + GPalette[i]);
  803.                 }
  804.             }
  805.         p++;
  806.         }
  807.     return(done);
  808. }
  809.  
  810. //---------------------------------------------------------------------------
  811.  
  812. void MorphPal(UBYTE st,UBYTE en,UWORD speed,UBYTE *palette)
  813. {
  814.     while(!MorphPalStep(st,en,speed,palette)) {
  815.         WaitTimer();
  816.         }
  817. }
  818.  
  819. //---------------------------------------------------------------------------
  820.  
  821. // Special morph palette that updates graphics while morphing - temporary.
  822.  
  823. void GMorphPal(UBYTE st,UBYTE en,UWORD speed,UBYTE *palette)
  824. {
  825.       UWORD p=0;
  826.       BOOL done=FALSE;
  827.  
  828.     void GRAPHICUpdate();
  829.  
  830.       while(!done) {
  831.         done=TRUE;
  832.         GRAPHICUpdate();
  833.         for(UWORD i=0;i<768;i+=3) {
  834.           if((i>=st*3) && (i<=en*3)) {
  835.                 for(UWORD sp=0;sp<speed;sp++) {
  836.                       if(GPalette[i]!=palette[i]) {
  837.                         if(GPalette[i]<palette[i]) GPalette[i]++;
  838.                         else GPalette[i]--;
  839.                         done=FALSE;
  840.                         }
  841.                       if(GPalette[i+1]!=palette[i+1]) {
  842.                         if(GPalette[i+1]<palette[i+1]) GPalette[i+1]++;
  843.                         else GPalette[i+1]--;
  844.                         done=FALSE;
  845.                         }
  846.                       if(GPalette[i+2]!=palette[i+2]) {
  847.                         if(GPalette[i+2]<palette[i+2]) GPalette[i+2]++;
  848.                         else GPalette[i+2]--;
  849.                         done=FALSE;
  850.                         }
  851.                       }
  852.             }
  853.  
  854.             PalDac(p, (GPalette[i+2] << 16) + (GPalette[i+1] << 8) + GPalette[i]);
  855.           p++;
  856.           }
  857.         }
  858. }
  859.  
  860. //===========================================================================
  861. // Map setup & offset tables setup
  862. //===========================================================================
  863.  
  864. void Copy2Svga(UBYTE *buf)
  865. {
  866.     UWORD i;
  867.  
  868.     WaitTimer();
  869.     for(i=0;i<5;i++) {
  870.         Svga.SetBank(i);
  871.         memcpy((BYTE *) 0xa0000,(BYTE *) buf+(i*65536),65536);
  872.         }
  873. }
  874.  
  875. //---------------------------------------------------------------------------
  876.  
  877. void Copy2SvgaArea(UBYTE *buf)
  878. {
  879.     UWORD i;
  880.  
  881.     WaitTimer();
  882.     for(i=0;i<4;i++) {
  883.         Svga.SetBank(i);
  884.         memcpy((BYTE *) 0xa0000,(BYTE *) buf+(i*65536),65536);
  885.         }
  886.     //Svga.SetBank(5);
  887.     //memcpy((BYTE *) 0xa0000,(BYTE *) buf+(5*65536),20480);
  888.     Svga.SetBank(4);
  889.     memcpy((BYTE *) 0xa0000,(BYTE *) buf+(4*65536),24576);
  890. }
  891.  
  892. //---------------------------------------------------------------------------
  893.  
  894. void MAPUpdateSetup()
  895. {
  896.    TUPDATE *m;
  897.    DWORD TopTile,BotTile;
  898.    WORD TopBank,BotBank;
  899.    DWORD x,y;
  900.    WORD tile;
  901.  
  902.    for(UWORD k=0;k<5;k++) bankstart[k]=0;
  903.    for(k=0;k<480;k++) Yoffset[k]=k*640;
  904.    for(k=0;k<MAPHEIGHT;k++) Moffset[k]=k*40;
  905.  
  906.    tile=0; x=0; y=0;
  907.    for(UWORD i=0;i<MAPHEIGHT;i++) {
  908.       x=0;
  909.       for(UWORD j=0;j<MAPWIDTH;j++) {
  910.          m=&MAPUpdate[tile];
  911.          m->update1=TRUE;
  912.          m->update2=TRUE;
  913.          m->x=x; m->y=y;
  914.  
  915.          TopTile=x+(y*640);
  916.          BotTile=(x+16)+((y+16)*640);
  917.  
  918.          m->offset=TopTile;
  919.  
  920.          m->bank1=(TopTile & 0xffff0000)>>16;
  921.          m->bank2=(BotTile & 0xffff0000)>>16;
  922.  
  923.          if(bankstart[m->bank1]==0) bankstart[m->bank1]=tile;
  924.          if(bankstart[m->bank2]==0) bankstart[m->bank2]=tile;
  925.  
  926.          m->lines2=((((y+16)*640)+x)&0x0000ffff)/640;
  927.          m->lines1=16-m->lines2;
  928.  
  929.          m->start1=(UBYTE *) 0xa0000+(((y*640)+x)&0x0000ffff);
  930.          m->start2=(UBYTE *) 0xa0000+((((y+m->lines1)*640)+x)&0x0000ffff);
  931.          m->phase=0;
  932.          m->buftop1=(UBYTE *) buf1+((y*640)+x);
  933.          m->bufbot1=(UBYTE *) buf1+(((y+m->lines1)*640)+x);
  934.          m->buftop2=(UBYTE *) buf2+((y*640)+x);
  935.          m->bufbot2=(UBYTE *) buf2+(((y+m->lines1)*640)+x);
  936.          tile++;
  937.          x+=16;
  938.          }
  939.      y+=16;
  940.      }
  941.    bankstart[0]=0;
  942. }
  943.  
  944. //===========================================================================
  945. // Map edge reset - resets edge of map for clipping
  946. //===========================================================================
  947.  
  948. void MAPResetEdge()
  949. {
  950.     DWORD i;
  951.    TUPDATE *m1,*m2;
  952.  
  953.    m1=&MAPUpdate[0];
  954.     for(i=0;i<MAPWIDTH;i++) {
  955.       m1->update1=FALSE;
  956.       m1->update2=FALSE;
  957.       m1->phase=0;
  958.  
  959.         (m1+MAPWIDTH)->update1=FALSE;
  960.       (m1+MAPWIDTH)->update2=FALSE;
  961.       (m1+MAPWIDTH)->phase=0;
  962.         m1++;
  963.         }
  964.  
  965.     m1=&MAPUpdate[0];
  966.    m2=&MAPUpdate[MAPWIDTH-1];
  967.     for(i=0;i<MAPHEIGHT;i++) {
  968.       m1->update1=FALSE;
  969.       m1->update2=FALSE;
  970.       m1->phase=0;
  971.       (m1+1)->update1=FALSE;
  972.       (m1+1)->update2=FALSE;
  973.       (m1+1)->phase=0;
  974.  
  975.         m2->update1=FALSE;
  976.       m2->update2=FALSE;
  977.       m2->phase=0;
  978.         (m2-1)->update1=FALSE;
  979.       (m2-1)->update2=FALSE;
  980.       (m2-1)->phase=0;
  981.  
  982.         m1+=MAPWIDTH;
  983.         m2+=MAPWIDTH;
  984.         }
  985. }
  986.  
  987. //===========================================================================
  988. // Sprite Functions
  989. //===========================================================================
  990.  
  991. void SPRITEResetAll()
  992. {
  993.     SPRITE *s=&GSprite[0];
  994.     for(UWORD i=0;i<NUMSPRITES;i++) {
  995.         s->active=FALSE;
  996.         s->update=FALSE;
  997.         s->forcedupdate=FALSE;
  998.         s->pri=0;
  999.         s->clag=0;
  1000.         s->anim=0;
  1001.         s->animpos=0;
  1002.         s->walk=FALSE;
  1003.         s->fly=FALSE;
  1004.         s->xmov=0;
  1005.         s->ymov=0;
  1006.         s->xcnt=0;
  1007.         s->ycnt=0;
  1008.         s->dline=NOLINE;
  1009.         s->spawnid=-1;
  1010.         s++;
  1011.         }
  1012. }
  1013.  
  1014. //---------------------------------------------------------------------------
  1015.  
  1016. // Find free sprite
  1017.  
  1018. UWORD SPRITEGetFree()
  1019. {
  1020.    SPRITE *s=&GSprite[1];
  1021.    for(UWORD i=1;i<NUMSPRITES;i++) if((s++)->active==FALSE) return(i);
  1022.    return(0);
  1023. }
  1024.  
  1025. //---------------------------------------------------------------------------
  1026.  
  1027. // Set sprite animation (Will not set if sprite already using same animation)
  1028.  
  1029. void SPRITEAnim(UWORD s,UWORD a,UWORD p)
  1030. {
  1031.     SPRITE *sa=&GSprite[s];
  1032.  
  1033.      if(sa->anim==a) return;
  1034.    sa->animpos=0;
  1035.    sa->anim=a;
  1036.    sa->image=NULL;
  1037.    sa->animtime=GOBJ[GSprite[s].id].ASpeed[a];
  1038.    sa->animcnt=1;
  1039.    sa->animtog=TRUE;
  1040.    sa->pri=p;
  1041. }
  1042.  
  1043. //---------------------------------------------------------------------------
  1044.  
  1045. // Set sprite animation (Forced animation)
  1046.  
  1047. void SPRITENewAnim(UWORD s,UWORD a,UWORD p)
  1048. {
  1049.     SPRITE *sa=&GSprite[s];
  1050.  
  1051.     sa->animpos=0;
  1052.    sa->anim=a;
  1053.    sa->image=NULL;
  1054.    sa->animtime=GOBJ[GSprite[s].id].ASpeed[a];
  1055.    sa->animcnt=1;
  1056.    sa->animtog=TRUE;
  1057.    sa->pri=p;
  1058. }
  1059.  
  1060. //---------------------------------------------------------------------------
  1061.  
  1062. // Work out line projection for flying sprite
  1063.  
  1064. void WorkoutLine(SPRITE *s,UWORD x1,UWORD y1,UWORD x2,UWORD y2)
  1065. {
  1066.    DWORD xDiff,yDiff,xInc,yInc,x,y;
  1067.  
  1068.    xDiff=((DWORD) abs(x1-x2)) << 16;
  1069.    yDiff=((DWORD) abs(y1-y2)) << 16;
  1070.    if (xDiff>yDiff) {
  1071.       xInc=1L<<16; yInc=yDiff/(xDiff>>16);
  1072.       }
  1073.    else {
  1074.       xInc=xDiff/(yDiff>>16); yInc=1L<<16;
  1075.       }
  1076.    if (x2 < x1) xInc= -xInc;
  1077.    if (y2 < y1) yInc= -yInc;
  1078.    x=((DWORD) x1) << 16;  y=((DWORD) y1) << 16;
  1079.    x+=xInc; y+=yInc;
  1080.  
  1081.    s->xinc=xInc;
  1082.    s->yinc=yInc;
  1083.    s->lpx=x;
  1084.    s->lpy=y;
  1085.    s->lx=x2;
  1086.    s->ly=y2;
  1087. }
  1088.  
  1089. //---------------------------------------------------------------------------
  1090.  
  1091. // Move sprite along line (Increasing with velocity s->sline)
  1092.  
  1093. void SpriteLine(SPRITE *s)
  1094. {
  1095.    UWORD spd=s->sline;
  1096.     UWORD Dr;
  1097.  
  1098.     if(s->pline!=0) {
  1099.       s->pline--;
  1100.       return;
  1101.       }
  1102.     if(s->yinc<0) Dr=0;  //Dr0=Up&Right Dr1=Up&Left Dr2=Dn&Right Dr3=Dn&Left
  1103.     else Dr=2;
  1104.     if(s->xinc<0) Dr++;
  1105.  
  1106.     s->lpx+=(s->xinc*spd); s->lpy+=(s->yinc*spd);
  1107.    s->x=(s->lpx+32767L)>>16; s->y=(s->lpy+32767L)>>16;
  1108.  
  1109.     switch(Dr) {
  1110.         case 0: //Up&Right
  1111.             if(s->y<s->ly) s->y=s->ly;
  1112.             if(s->x>s->lx) s->x=s->lx;
  1113.             break;
  1114.         case 1: //Up&Left
  1115.             if(s->y<s->ly) s->y=s->ly;
  1116.             if(s->x<s->lx) s->x=s->lx;
  1117.             break;
  1118.         case 2: //Dn&Right
  1119.             if(s->y>s->ly) s->y=s->ly;
  1120.             if(s->x>s->lx) s->x=s->lx;
  1121.             break;
  1122.         case 3: //Dn&Left
  1123.             if(s->y>s->ly) s->y=s->ly;
  1124.             if(s->x<s->lx) s->x=s->lx;
  1125.             break;
  1126.         }
  1127.  
  1128.    if(s->sline<24) s->sline++;
  1129. }
  1130.  
  1131. //---------------------------------------------------------------------------
  1132.  
  1133. // Prepare the sprites and map details for printing sprites
  1134.  
  1135. void SPRITEPrepare()
  1136. {
  1137.    TUPDATE *m;
  1138.    SPRITE *s,*n;
  1139.    UWORD sx,sy;
  1140.    UDWORD st;
  1141.    UWORD com,anm,spawnspr;
  1142.    BOOL  AnimUpdate;
  1143.  
  1144.    //Check spawning sprites
  1145.  
  1146.    s=&GSprite[0];
  1147.    for(UWORD i=0;i<NUMSPRITES;i++) {
  1148.      if(s->active==TRUE && s->spawnid!=-1) {
  1149.         if(s->spawncnt==0) {
  1150.            s->spawncnt=s->spawntime;
  1151.            spawnspr=SPRITEGetFree();
  1152.               n=&GSprite[spawnspr];
  1153.                n->id=s->spawnid;
  1154.                n->line=-1;
  1155.                n->walk=FALSE;
  1156.                n->fly=FALSE;
  1157.                n->oldx=0;
  1158.                n->oldy=0;
  1159.                n->xmov=0;
  1160.                n->ymov=0;
  1161.                n->x=s->x;
  1162.                n->y=s->y;
  1163.                n->active=TRUE;
  1164.                SPRITENewAnim(spawnspr,0,1);
  1165.            }
  1166.         else s->spawncnt--;
  1167.         }
  1168.          s++;
  1169.          }
  1170.  
  1171.    //1st Pass - update sprites that have moved/animated
  1172.  
  1173.    s=&GSprite[0];
  1174.    for(i=0;i<NUMSPRITES;i++) {
  1175.       if(s->active==TRUE) {
  1176.          AnimUpdate=FALSE;
  1177.          if(s->animtog==TRUE) {
  1178.                  s->animcnt--;
  1179.                  if(s->animcnt==0) {
  1180.                        s->animcnt=s->animtime;
  1181.                        GFRM=GOBJ[s->id].FRMList;
  1182.                        GDAT=GOBJ[s->id].GData;
  1183.                        GANM=GOBJ[s->id].AData;
  1184.  
  1185.                        com=GANM[s->anim][s->animpos].p1;
  1186.                        anm=GANM[s->anim][s->animpos].p2;
  1187.  
  1188.                    if(com!=5) {
  1189.                          s->image=GDAT[GFRM[anm-1]];
  1190.                          AnimUpdate=TRUE;
  1191.                          s->animpos++;
  1192.                          com=GANM[s->anim][s->animpos].p1;
  1193.                          if(com==1 || com==2) s->animpos=0;
  1194.                          if(com==2) s->animtog=FALSE;
  1195.                          }
  1196.                        else {
  1197.                          s->active=FALSE;
  1198.                          s->clag=0;
  1199.                          s->xcnt=0; s->ycnt=0;
  1200.                          s->oldx=0; s->oldy=0;
  1201.                          s->spawnid=-1;
  1202.                          s->id=0;
  1203.                         s->dline=NOLINE;
  1204.                          AnimUpdate=TRUE;
  1205.                          }
  1206.                        }
  1207.                }
  1208.          if(s->clag>0) s->clag--;
  1209.          s->oldx=s->x; s->oldy=s->y;
  1210.  
  1211.          if(s->dline!=NOLINE) SpriteLine(s);
  1212.          if(s->xcnt!=0) {
  1213.                 s->xcnt--;
  1214.                 s->x+=s->xmov;
  1215.                 }
  1216.          if(s->ycnt!=0) {
  1217.                s->ycnt--;
  1218.                s->y+=s->ymov;
  1219.                }
  1220.  
  1221.            if((s->x!=s->oldx)||(s->y!=s->oldy)||(AnimUpdate==TRUE)||(s->forcedupdate==TRUE)) {
  1222.                  s->update=TRUE;
  1223.                   s->forcedupdate=FALSE;
  1224.                  sx=s->x; sy=s->y;
  1225.                  st=Moffset[sy>>4]+(sx>>4);
  1226.  
  1227.                   m=&MAPUpdate[st];
  1228.                  m->phase=2;
  1229.                 (m+1)->phase=2;
  1230.                 (m+MAPWIDTH)->phase=2;
  1231.                 (m+MAPWIDTH+1)->phase=2;
  1232.                  if((sx & 0x000f) !=0) {
  1233.                     (m+2)->phase=2;
  1234.                     (m+MAPWIDTH+2)->phase=2;
  1235.                     }
  1236.  
  1237.                  if((sy & 0x000f) !=0) {
  1238.                        (m+MAPWIDTH+MAPWIDTH)->phase=2;
  1239.                     (m+MAPWIDTH+MAPWIDTH+1)->phase=2;
  1240.                        if((sx & 0x000f) !=0) {
  1241.                         (m+MAPWIDTH+MAPWIDTH+2)->phase=2;
  1242.                         }
  1243.                        }
  1244.                  }
  1245.            if(((s->x!=s->oldx)||(s->y!=s->oldy)) && s->oldx!=0 && s->oldy!=0) {
  1246.                  sx=s->oldx; sy=s->oldy;
  1247.                  st=Moffset[sy>>4]+(sx>>4);
  1248.  
  1249.                  m=&MAPUpdate[st];
  1250.                  if(m->phase==0) m->phase=1;
  1251.                 if((m+1)->phase==0) (m+1)->phase=1;
  1252.                  if((m+MAPWIDTH)->phase==0) (m+MAPWIDTH)->phase=1;
  1253.                 if((m+MAPWIDTH+1)->phase==0) (m+MAPWIDTH+1)->phase=1;
  1254.  
  1255.                 if((sx & 0x000f) !=0) {
  1256.                     if((m+2)->phase==0) (m+2)->phase=1;
  1257.                     if((m+MAPWIDTH+2)->phase==0) (m+MAPWIDTH+2)->phase=1;
  1258.                     }
  1259.                  if((sy & 0x000f) !=0) {
  1260.                        if((m+MAPWIDTH+MAPWIDTH)->phase==0) (m+MAPWIDTH+MAPWIDTH)->phase=1;
  1261.                        if((m+MAPWIDTH+MAPWIDTH+1)->phase==0) (m+MAPWIDTH+MAPWIDTH+1)->phase=1;
  1262.                        if((sx & 0x000f) !=0) {
  1263.                         if((m+MAPWIDTH+MAPWIDTH+2)->phase==0) (m+MAPWIDTH+MAPWIDTH+2)->phase=1;
  1264.                         }
  1265.                        }
  1266.                  }
  1267.            if((s->dline!=NOLINE) && (s->y==s->ly && s->x==s->lx)) {
  1268.                   if(s->dline==SPRLINEKILL) {
  1269.                        s->active=FALSE;
  1270.                        s->clag=0;
  1271.                        }
  1272.                  s->dline=NOLINE;
  1273.                  s->sline=0;
  1274.                  s->spawnid=-1;
  1275.                  }
  1276.           }
  1277.       s++;
  1278.       }
  1279.  
  1280.    //2nd Pass - update sprites that have been overwritten by the 1st pass
  1281.  
  1282.    s=&GSprite[0];
  1283.    for(i=0;i<NUMSPRITES;i++) {
  1284.       if(s->active==TRUE && s->update==FALSE) {
  1285.             AnimUpdate=FALSE;
  1286.             sx=s->x; sy=s->y;
  1287.             st=Moffset[sy>>4]+(sx>>4);
  1288.             m=&MAPUpdate[st];
  1289.               if(m->phase>0) AnimUpdate=TRUE;
  1290.               if((m+1)->phase>0) AnimUpdate=TRUE;
  1291.             if((m+MAPWIDTH)->phase>0) AnimUpdate=TRUE;
  1292.             if((m+MAPWIDTH+1)->phase>0) AnimUpdate=TRUE;
  1293.  
  1294.             if((sx & 0x000f) !=0) {
  1295.                 if((m+2)->phase>0) AnimUpdate=TRUE;
  1296.                 if((m+MAPWIDTH+2)->phase>0) AnimUpdate=TRUE;
  1297.                 }
  1298.             if((sy & 0x000f) !=0) {
  1299.                   if((m+MAPWIDTH+MAPWIDTH)->phase>0) AnimUpdate=TRUE;
  1300.                   if((m+MAPWIDTH+MAPWIDTH+1)->phase>0) AnimUpdate=TRUE;
  1301.                   if((sx & 0x000f) !=0) {
  1302.                     if((m+MAPWIDTH+MAPWIDTH+2)->phase>0) AnimUpdate=TRUE;
  1303.                     }
  1304.                   }
  1305.  
  1306.             if(AnimUpdate==TRUE) {
  1307.                   s->update=TRUE;
  1308.                   m->update1=TRUE;
  1309.                   m->update2=TRUE;
  1310.                   if((sx & 0x000f) !=0) {
  1311.                         (m+1)->update1=TRUE;
  1312.                       (m+1)->update2=TRUE;
  1313.                         (m+2)->update1=TRUE;
  1314.                       (m+2)->update2=TRUE;
  1315.                       }
  1316.                 if((sy & 0x000f) !=0) {
  1317.                       (m+MAPWIDTH)->update1=TRUE;
  1318.                       (m+MAPWIDTH)->update2=TRUE;
  1319.                       (m+MAPWIDTH+MAPWIDTH)->update1=TRUE;
  1320.                       (m+MAPWIDTH+MAPWIDTH)->update2=TRUE;
  1321.                       if((sx & 0x000f) !=0) {
  1322.                         (m+MAPWIDTH+1)->update1=TRUE;
  1323.                         (m+MAPWIDTH+1)->update2=TRUE;
  1324.                         (m+MAPWIDTH+2)->update1=TRUE;
  1325.                         (m+MAPWIDTH+2)->update2=TRUE;
  1326.                         (m+MAPWIDTH+MAPWIDTH+1)->update1=TRUE;
  1327.                         (m+MAPWIDTH+MAPWIDTH+1)->update2=TRUE;
  1328.                         (m+MAPWIDTH+MAPWIDTH+2)->update1=TRUE;
  1329.                         (m+MAPWIDTH+MAPWIDTH+2)->update2=TRUE;
  1330.                         }
  1331.                       }
  1332.                 }
  1333.           }
  1334.        s++;
  1335.        }
  1336. }
  1337.  
  1338. //---------------------------------------------------------------------------
  1339.  
  1340. // Refresh sprite buffer with 16x16 from background buffer
  1341.  
  1342. void BACKRefresh()
  1343. {
  1344.    TUPDATE *m;
  1345.  
  1346.    m=&MAPUpdate[0];
  1347.    for(UWORD j=0;j<MAPSIZE;j++) {
  1348.         if(m->phase!=0) {
  1349.           m->update1=TRUE;
  1350.           m->update2=TRUE;
  1351.           BUFBlitTile32x32(m->buftop2,m->buftop1,16);
  1352.           m->phase--;
  1353.           }
  1354.         m++;
  1355.         }
  1356. }
  1357.  
  1358. //---------------------------------------------------------------------------
  1359.  
  1360. // Refresh sprite buffer update values
  1361.  
  1362. void BACKMapRefresh()
  1363. {
  1364.    TUPDATE *m;
  1365.  
  1366.    m=&MAPUpdate[0];
  1367.    for(UWORD j=0;j<MAPSIZE;j++) {
  1368.         if(m->phase!=0) {
  1369.           m->update1=TRUE;
  1370.           m->update2=TRUE;
  1371.           m->phase--;
  1372.           }
  1373.         m++;
  1374.         }
  1375. }
  1376.  
  1377. //---------------------------------------------------------------------------
  1378.  
  1379. // Print active sprite images to sprite buffer
  1380.  
  1381. void SPRITEUpdate()
  1382. {
  1383.    TUPDATE *m;
  1384.    SPRITE *s;
  1385.    UWORD sx,sy;
  1386.    UDWORD st;
  1387.  
  1388.       s=&GSprite[0];
  1389.       for(UWORD i=0;i<NUMSPRITES;i++) {
  1390.         if(s->active==TRUE && s->update==TRUE && s->pri==2) {
  1391.           sx=s->x; sy=s->y;
  1392.             BlitComp8Sprite32x32(s->image,buf1+Yoffset[sy]+sx);
  1393.           s->update=FALSE;
  1394.           }
  1395.         s++;
  1396.         }
  1397.       s=&GSprite[0];
  1398.       for(i=0;i<NUMSPRITES;i++) {
  1399.         if(s->active==TRUE && s->update==TRUE && s->pri==1) {
  1400.           sx=s->x; sy=s->y;
  1401.             BlitComp8Sprite32x32(s->image,buf1+Yoffset[sy]+sx);
  1402.           s->update=FALSE;
  1403.           }
  1404.         s++;
  1405.         }
  1406.       s=&GSprite[0];
  1407.       for(i=0;i<NUMSPRITES;i++) {
  1408.         if(s->active==TRUE && s->update==TRUE && s->pri==0) {
  1409.           sx=s->x; sy=s->y;
  1410.             BlitComp8Sprite32x32(s->image,buf1+Yoffset[sy]+sx);
  1411.           s->update=FALSE;
  1412.           }
  1413.         s++;
  1414.         }
  1415. }
  1416.  
  1417. //---------------------------------------------------------------------------
  1418.  
  1419. // Update sprites to buffer 2
  1420.  
  1421. void SPRITEUpdateBuffer2()
  1422. {
  1423.    TUPDATE *m;
  1424.    SPRITE *s;
  1425.    UWORD sx,sy;
  1426.    UDWORD st;
  1427.  
  1428.       s=&GSprite[0];
  1429.       for(UWORD i=0;i<NUMSPRITES;i++) {
  1430.         if(s->active==TRUE && s->update==TRUE && s->pri==2) {
  1431.           sx=s->x; sy=s->y;
  1432.             BlitComp8Sprite32x32(s->image,buf2+Yoffset[sy]+sx);
  1433.           s->update=FALSE;
  1434.           }
  1435.         s++;
  1436.         }
  1437.       s=&GSprite[0];
  1438.       for(i=0;i<NUMSPRITES;i++) {
  1439.         if(s->active==TRUE && s->update==TRUE && s->pri==1) {
  1440.           sx=s->x; sy=s->y;
  1441.             BlitComp8Sprite32x32(s->image,buf2+Yoffset[sy]+sx);
  1442.           s->update=FALSE;
  1443.           }
  1444.         s++;
  1445.         }
  1446.       s=&GSprite[0];
  1447.       for(i=0;i<NUMSPRITES;i++) {
  1448.         if(s->active==TRUE && s->update==TRUE && s->pri==0) {
  1449.           sx=s->x; sy=s->y;
  1450.             BlitComp8Sprite32x32(s->image,buf2+Yoffset[sy]+sx);
  1451.           s->update=FALSE;
  1452.           }
  1453.         s++;
  1454.         }
  1455. }
  1456.  
  1457. //---------------------------------------------------------------------------
  1458.  
  1459. // Imprint font sprites onto all buffers
  1460.  
  1461. void FONTImprint()
  1462. {
  1463.       TUPDATE *m;
  1464.       SPRITE *s;
  1465.       UWORD sx,sy;
  1466.       UDWORD st;
  1467.  
  1468.       s=&GSprite[0];
  1469.       for(UWORD i=0;i<NUMSPRITES;i++) {
  1470.         if(s->active==TRUE && s->update==TRUE) {
  1471.           sx=s->x; sy=s->y;
  1472.             BlitComp8SSprite32x32(s->image,buf1+Yoffset[sy]+sx);
  1473.             BlitComp8SSprite32x32(s->image,buf2+Yoffset[sy]+sx);
  1474.           s->update=FALSE;
  1475.           }
  1476.         s++;
  1477.         }
  1478. }
  1479.  
  1480. //---------------------------------------------------------------------------
  1481.  
  1482. // Update changed 32x32's from the logical buffer to the physical screen
  1483.  
  1484. void MAPRefresh()
  1485. {
  1486.       TUPDATE *m;
  1487.  
  1488.       for(UWORD b=0;b<5;b++) {
  1489.         Svga.SetBank(b);
  1490.         UWORD i=bankstart[b];
  1491.         m=&MAPUpdate[i];
  1492.         do {
  1493.           if(m->update1==TRUE) {
  1494.                 if(m->bank1==b) {
  1495.                   if(m->bank1==m->bank2) BUFBlitTile32x32(m->buftop1,m->start1,16);
  1496.                   else BUFBlitTile32x32(m->buftop1,m->start1,m->lines1);
  1497.                       m->update1=FALSE;
  1498.                   }
  1499.                 }
  1500.           else {
  1501.                 if((m->bank1!=m->bank2) && m->bank2==b) {
  1502.                    if(m->update2==TRUE) BUFBlitTile32x32(m->bufbot1,m->start2,m->lines2);
  1503.                   m->update2=FALSE;
  1504.                     }
  1505.                 }
  1506.           m++;
  1507.           } while(i++<MAPSIZE && (m->bank1==b || m->bank2==b));
  1508.         }
  1509. }
  1510.  
  1511. //===========================================================================
  1512. // Game graphic refresh functions
  1513. //===========================================================================
  1514.  
  1515. // Network update function
  1516.  
  1517. void NET_Update()
  1518. {
  1519.     if( NET_Installed && ( GameMode == MULTI ) ) {
  1520.         NET_Player_Score = GScore;
  1521.         NETUserCycle();
  1522.         }
  1523. }
  1524.  
  1525. // In-Game graphic update
  1526.  
  1527. void GRAPHICUpdate()
  1528. {
  1529.     WaitTimer();
  1530.  
  1531.     NET_Update();
  1532.  
  1533.     MAPRefresh();
  1534.       SPRITEPrepare();
  1535.     BACKRefresh();
  1536.       SPRITEUpdate();
  1537. }
  1538.  
  1539. //---------------------------------------------------------------------------
  1540.  
  1541. void GRAPHICUpdateNoVr()
  1542. {
  1543.     MAPRefresh();
  1544.       SPRITEPrepare();
  1545.     BACKRefresh();
  1546.       SPRITEUpdate();
  1547. }
  1548.  
  1549. //---------------------------------------------------------------------------
  1550.  
  1551. void GRAPHICUpdateNotVisible()
  1552. {
  1553.       SPRITEPrepare();
  1554.       SPRITEUpdate();
  1555. }
  1556.  
  1557. //---------------------------------------------------------------------------
  1558.  
  1559. void PANELUpdate()
  1560. {
  1561.     extern void ScoreTrack();
  1562.    extern void KillsTrack();
  1563.    extern void LevelsTrack();
  1564.  
  1565.     ScoreTrack();
  1566.    KillsTrack();
  1567.    LevelsTrack();
  1568. }
  1569.  
  1570. //---------------------------------------------------------------------------
  1571.  
  1572. // Fixed font update (same as sprite but leaves imprint of image)
  1573.  
  1574. void FONTUpdate()
  1575. {
  1576.       MAPRefresh();
  1577.  
  1578.       SPRITEPrepare();
  1579.       BACKRefresh();
  1580.       FONTImprint();
  1581. }
  1582.  
  1583. //===========================================================================
  1584. // Main Game functions
  1585. //===========================================================================
  1586.  
  1587. void GLineSetup()
  1588. {
  1589.     DWORD i;
  1590.  
  1591.       for(i=0;i<NUMLINES;i++) {
  1592.         GLine[i].backcolor = 0;
  1593.         GLine[i].count = 0;
  1594.         GLine[i].wait = 0;
  1595.         }
  1596. }
  1597.  
  1598. // Game setup
  1599.  
  1600. void GSetup()
  1601. {
  1602.       TUPDATE *m;
  1603.  
  1604.       m=&MAPUpdate[0];
  1605.       for(UWORD j=0;j<MAPSIZE;j++) {
  1606.         m->update1=TRUE;
  1607.         m->update2=TRUE;
  1608.         m++;
  1609.         }
  1610.       memcpy(buf1,buf2,300000);
  1611.  
  1612.       for(UWORD i=0;i<NUMSPRITES;i++) {
  1613.         GSprite[i].active=FALSE;
  1614.         GSprite[i].forcedupdate=FALSE;
  1615.         GSprite[i].clag=0;
  1616.         GSprite[i].update=1;
  1617.         GSprite[i].xmov=0;
  1618.         GSprite[i].ymov=0;
  1619.         GSprite[i].xcnt=0;
  1620.         GSprite[i].ycnt=0;
  1621.         GSprite[i].dline=NOLINE;
  1622.         GSprite[i].walk=FALSE;
  1623.         GSprite[i].fly=FALSE;
  1624.         GSprite[i].spawnid=-1;
  1625.         GSprite[i].lx=0;
  1626.         GSprite[i].ly=0;
  1627.         }
  1628.  
  1629.       GLastQuad=-1;
  1630.     GLineSetup();
  1631.  
  1632.       for(i=0;i<768;i++) {
  1633.         WPalette[i]=63;
  1634.         TPalette[i]=63;
  1635.         }
  1636.       TPalette[0]=0; TPalette[1]=0; TPalette[2]=0;
  1637.  
  1638.     // Real state variables
  1639.  
  1640.       OldLevel=-1;
  1641.       GScore=0; GBScore=0; Accum=1; GBKills=0; TotalKills=0;
  1642.       GPlayerFacing=FACEUP;
  1643.       LastKill=-1;
  1644.       LastLineKill=0;
  1645.       WalkLine=-1;
  1646.       FireWait=0;
  1647.       NEWspr=-1;
  1648.       MOVquadline=-1;
  1649.       AppearCount=-1;
  1650.       LastBombQuad=-1;
  1651.       NumBombs=0;
  1652.       Strobe=FALSE;
  1653.       StrobeVal1=0;
  1654.     StrobeVal2=0;
  1655.     StrobeSound=0;
  1656.     Bomb2Sound=FALSE;
  1657.     SpringFull=0;
  1658.       BonusCount=0;
  1659.     DoingLeadIn=FALSE;
  1660.     FireEnableStatus=TRUE;
  1661.     LineState=BEING_BUILT;
  1662.  
  1663.     // Events
  1664.  
  1665.     EVENT_AddBlock = 0;
  1666.     EVENT_Bonus = 0;
  1667.     EVENT_SpeedUp = 0;
  1668.     SpeedUpDuration = 0;
  1669.     EVENT_BlowUp = 0;
  1670.     EVENT_AddTarget = 0;
  1671.     EVENT_Pause = FALSE;
  1672.  
  1673.     NETSEQUENCE = 0;
  1674.     NETSEQUENCECOUNT = 0;
  1675.  
  1676.     // Timer
  1677.  
  1678.     TimerCount = 0;
  1679. }
  1680.  
  1681. //---------------------------------------------------------------------------
  1682. // Set network player name in sprites
  1683. //---------------------------------------------------------------------------
  1684.  
  1685. void NetSetName( DWORD x, BYTE *s )
  1686. {
  1687.     DWORD i;
  1688.       UWORD fs;
  1689.     BYTE *p = s, c;
  1690.  
  1691.       for( i=0; i<5; i++ ) {
  1692.         c = *p;
  1693.         if( c == 0 ) c = 32;
  1694.         else p++;
  1695.  
  1696.         if( c != NET_Name_Letter[ x + i ] ) {
  1697.             NET_Name_Letter[ x + i ] = c;
  1698.             fs = NET_Name_Sprite[ x + i ];
  1699.             GSprite[fs].active=TRUE;
  1700.             GSprite[fs].id=NETFONT;
  1701.             if( c  >='A' &&  c  <='Z') {
  1702.               SPRITENewAnim(fs,( c - 65),0);
  1703.               }
  1704.             if( c ==' ') {
  1705.               SPRITENewAnim(fs,47,0);
  1706.               }
  1707.             if( c =='!') {
  1708.               SPRITENewAnim(fs,36,0);
  1709.               }
  1710.             if( c =='+') {
  1711.               SPRITENewAnim(fs,37,0);
  1712.               }
  1713.             if( c =='-') {
  1714.               SPRITENewAnim(fs,38,0);
  1715.               }
  1716.             if( c =='.') {
  1717.               SPRITENewAnim(fs,39,0);
  1718.               }
  1719.             if( c =='?') {
  1720.               SPRITENewAnim(fs,40,0);
  1721.               }
  1722.             if( c =='{') {
  1723.               SPRITENewAnim(fs,41,0);
  1724.               }
  1725.             if( c =='}') {
  1726.               SPRITENewAnim(fs,42,0);
  1727.               }
  1728.             if( c =='[') {
  1729.               SPRITENewAnim(fs,43,0);
  1730.               }
  1731.             if( c ==']') {
  1732.               SPRITENewAnim(fs,44,0);
  1733.               }
  1734.             if( c =='#') {
  1735.               SPRITENewAnim(fs,45,0);
  1736.               }
  1737.             if( c ==':') {
  1738.               SPRITENewAnim(fs,46,0);
  1739.               }
  1740.             if( c >='0' &&  c <='9') {
  1741.               SPRITENewAnim(fs,( c - 48 ) + 26,0);
  1742.               }
  1743.             }
  1744.         }
  1745. }
  1746.  
  1747. //---------------------------------------------------------------------------
  1748.  
  1749. void Net_Refresh_Names()
  1750. {
  1751.     BYTE *n;
  1752.     BYTE blank[] = "     ";
  1753.     DWORD p;
  1754.  
  1755.     if( NET_Game == 0 ) return;
  1756.  
  1757.     NetSetName( 0, NET_Player_Name );
  1758.  
  1759.     for( p=0; p<3; p++ ) {
  1760.         n = NETGetPlayerName( p );
  1761.         if( n != NULL ) {
  1762.             if( NETGetPlayerType( p ) == NET_GAME_PLAYER ) NetSetName( ( p+1 ) * 5, n );
  1763.             }
  1764.         else NetSetName( ( p+1 ) * 5, blank );
  1765.         }
  1766. }
  1767.  
  1768. //---------------------------------------------------------------------------
  1769.  
  1770. BOOL Net_Check_Won()
  1771. {
  1772.     if( NET_Game == 0 ) return( FALSE );
  1773.     if( NETFindGamePlayer() ) return( FALSE );
  1774.     if( NET_Player_Count == 0 ) return( TRUE );
  1775.     return( FALSE );
  1776. }
  1777.  
  1778. //---------------------------------------------------------------------------
  1779.  
  1780. void KillHarmless( WORD i, UWORD l )
  1781. {
  1782.     SPRITE *s = &GSprite[i];
  1783.     BOOL KillSp;
  1784.  
  1785.     if( !s->active ) return;
  1786.  
  1787.    KillSp=FALSE;
  1788.    if((s->id>COLOR4 && ( s->id<EXPLODE) || (s->id==BONUSB)) && s->line == l ) {
  1789.        if(s->quad==0 && s->y==160-32) KillSp=TRUE;
  1790.        if(s->quad==1 && s->x==352+32) KillSp=TRUE;
  1791.        if(s->quad==2 && s->y==256+32) KillSp=TRUE;
  1792.        if(s->quad==3 && s->x==256-32) KillSp=TRUE;
  1793.        }
  1794.    if(KillSp==TRUE && s->fly!=TRUE) {
  1795.        s->id=EXPLODE;
  1796.        s->walk=FALSE;
  1797.        s->oldx=0;
  1798.        s->oldy=0;
  1799.        s->xmov=0;
  1800.        s->ymov=0;
  1801.        SPRITENewAnim(i,0,0);
  1802.        }
  1803. }
  1804.  
  1805. //---------------------------------------------------------------------------
  1806.  
  1807. // Set all the sprites next to each other on a line to move and animate
  1808.  
  1809. void MoveLine(UWORD l,WORD mx,WORD my,WORD cx,WORD cy,WORD anm)
  1810. {
  1811.     WORD QMove[10];
  1812.     WORD QNum;
  1813.       WORD QLine=(l-1)>>2;
  1814.     WORD i,j,tmp,cp;
  1815.     BOOL StopIt;
  1816.     BOOL MoveIt;
  1817.     SPRITE *s;
  1818.  
  1819.     //Figure out which sprites are on a line and sort them to lowest first
  1820.     QNum=0;
  1821.     s=&GSprite[1];
  1822.     if(QLine==1 || QLine==3) {  //Use X to sort
  1823.           for(i=1;i<NUMSPRITES;i++) {
  1824.             KillHarmless( i, l );    //Kill bombs/springs on moving to middle
  1825.             if(s->active==TRUE && (s->id<EXPLODE || (s->id==BONUSB)) && s->line==l) {
  1826.                 QMove[QNum]=i;
  1827.                 if(QNum!=0) {  //Sort to correct place in queue
  1828.                     cp=s->x;
  1829.                     j=QNum-1;
  1830.                     while((j!=-1) && (cp<GSprite[QMove[j]].x)) {
  1831.                         QMove[j+1]=QMove[j];
  1832.                         QMove[j]=i;
  1833.                         j--;
  1834.                        }
  1835.                     }
  1836.                 QNum++;
  1837.               }
  1838.             s++;
  1839.            }
  1840.         }
  1841.     else {  //Use Y to sort
  1842.         for(i=1;i<NUMSPRITES;i++) {
  1843.             KillHarmless( i, l );    //Kill bombs/springs on moving to middle
  1844.             if(s->active==TRUE && (s->id<EXPLODE || (s->id==BONUSB)) && s->line==l) {
  1845.                 QMove[QNum]=i;
  1846.                 if(QNum!=0) {  //Sort to correct place in queue
  1847.                     cp=s->y;
  1848.                     j=QNum-1;
  1849.                     while((j!=-1) && (cp<GSprite[QMove[j]].y)) {
  1850.                         QMove[j+1]=QMove[j];
  1851.                         QMove[j]=i;
  1852.                         j--;
  1853.                        }
  1854.                     }
  1855.                 QNum++;
  1856.               }
  1857.             s++;
  1858.            }
  1859.         }
  1860.  
  1861.     if(QNum==0) return;  //No sprites at all on this line!
  1862.  
  1863.     StopIt=FALSE;
  1864.     switch(QLine) {
  1865.         case 0: //Up
  1866.             for(i=0;(i<QNum) && (StopIt==FALSE);i++) {
  1867.                 MoveIt=FALSE;
  1868.                 s=&GSprite[QMove[i]];
  1869.                 if(i!=0) {
  1870.                     if(s->y == (GSprite[QMove[i-1]].y+32)) MoveIt=TRUE;  //Joined
  1871.                     else StopIt=TRUE; // A split line - continue no further!
  1872.                     }
  1873.                 else {
  1874.                     if(s->y == 0) MoveIt=TRUE; //First on line
  1875.                     else StopIt=TRUE; //No link to start of line
  1876.                     }
  1877.                 if(MoveIt==TRUE) {
  1878.                    s->xmov=mx; s->ymov=my;
  1879.                    s->xcnt=cx; s->ycnt=cy;
  1880.                    if(s->id<BONUSB) SPRITENewAnim(QMove[i],anm,1);
  1881.                    else SPRITENewAnim(QMove[i],(NET_Game * 5),1);
  1882.                    s->walk=TRUE;
  1883.                    WalkLine=l;
  1884.                     }
  1885.  
  1886.                 }
  1887.             break;
  1888.  
  1889.         case 3: //Left
  1890.             for(i=0;(i<QNum) && (StopIt==FALSE);i++) {
  1891.                 MoveIt=FALSE;
  1892.                 s=&GSprite[QMove[i]];
  1893.                 if(i!=0) {
  1894.                     if(s->x == (GSprite[QMove[i-1]].x+32)) MoveIt=TRUE;  //Joined
  1895.                     else StopIt=TRUE; // A split line - continue no further!
  1896.                     }
  1897.                 else {
  1898.                     if(s->x == 0) MoveIt=TRUE; //First on line
  1899.                     else StopIt=TRUE; //No link to start of line
  1900.                     }
  1901.                 if(MoveIt==TRUE) {
  1902.                    s->xmov=mx; s->ymov=my;
  1903.                    s->xcnt=cx; s->ycnt=cy;
  1904.                    if(s->id<BONUSB) SPRITENewAnim(QMove[i],anm,1);
  1905.                    else SPRITENewAnim(QMove[i],(NET_Game * 5),1);
  1906.                    s->walk=TRUE;
  1907.                    WalkLine=l;
  1908.                     }
  1909.  
  1910.                 }
  1911.             break;
  1912.         case 1: //Right
  1913.             for(i=QNum-1;(i>-1) && (StopIt==FALSE);i--) {
  1914.                 MoveIt=FALSE;
  1915.                 s=&GSprite[QMove[i]];
  1916.                 if(i!=QNum-1) {
  1917.                     if(s->x == (GSprite[QMove[i+1]].x-32)) MoveIt=TRUE;  //Joined
  1918.                     else StopIt=TRUE; // A split line - continue no further!
  1919.                     }
  1920.                 else {
  1921.                     if(s->x == 608) MoveIt=TRUE; //First on line
  1922.                     else StopIt=TRUE; //No link to start of line
  1923.                     }
  1924.                 if(MoveIt==TRUE) {
  1925.                    s->xmov=mx; s->ymov=my;
  1926.                    s->xcnt=cx; s->ycnt=cy;
  1927.                    if(s->id<BONUSB) SPRITENewAnim(QMove[i],anm,1);
  1928.                    else SPRITENewAnim(QMove[i],(NET_Game * 5),1);
  1929.                    s->walk=TRUE;
  1930.                    WalkLine=l;
  1931.                     }
  1932.  
  1933.                 }
  1934.             break;
  1935.         case 2: //Bottom
  1936.             for(i=QNum-1;(i>-1) && (StopIt==FALSE);i--) {
  1937.                 MoveIt=FALSE;
  1938.                 s=&GSprite[QMove[i]];
  1939.                 if(i!=QNum-1) {
  1940.                     if(s->y == (GSprite[QMove[i+1]].y-32)) MoveIt=TRUE;  //Joined
  1941.                     else StopIt=TRUE; // A split line - continue no further!
  1942.                     }
  1943.                 else {
  1944.                     if(s->y == 416) MoveIt=TRUE; //First on line
  1945.                     else StopIt=TRUE; //No link to start of line
  1946.                     }
  1947.                 if(MoveIt==TRUE) {
  1948.                    s->xmov=mx; s->ymov=my;
  1949.                    s->xcnt=cx; s->ycnt=cy;
  1950.                    if(s->id<BONUSB) SPRITENewAnim(QMove[i],anm,1);
  1951.                    else SPRITENewAnim(QMove[i],(NET_Game * 5),1);
  1952.                    s->walk=TRUE;
  1953.                    WalkLine=l;
  1954.                     }
  1955.  
  1956.                 }
  1957.             break;
  1958.         }
  1959. }
  1960.  
  1961. //---------------------------------------------------------------------------
  1962.  
  1963. // Workout the number of sprites in all lines and the number of Spring icons
  1964.  
  1965. void FindLineCount()
  1966. {
  1967.       SPRITE *s;
  1968.       s=&GSprite[0];
  1969.  
  1970.       for(UWORD i=0;i<NUMLINES;i++) {
  1971.         GLine[i].count=0;
  1972.         }
  1973.       BonusCount=0;
  1974.  
  1975.     NET_Player_Blocks = 0;
  1976.     NET_Player_Springs = SpringFull;
  1977.  
  1978.       for(i=1;i<NUMSPRITES;i++) {
  1979.         if(s->active==TRUE && s->line>0 && (s->id<EXPLODE || (s->id==BONUSB))) {
  1980.           GLine[s->line-1].count++;
  1981.           if(s->id==BONUSB) {
  1982.                 BonusCount++;
  1983.                 }
  1984.           NET_Player_Blocks++;
  1985.             }
  1986.         s++;
  1987.         }
  1988.       for(i=0;i<NUMLINES;i++) {
  1989.         if(GLine[i].count==0) GLine[i].wait = 0;
  1990.         else if(GLine[i].wait > 0) GLine[i].wait--;
  1991.         }
  1992. }
  1993.  
  1994. //---------------------------------------------------------------------------
  1995.  
  1996. // Find the number of bombs in existence
  1997.  
  1998. void FindNumBombs()
  1999. {
  2000.       SPRITE *s;
  2001.       s=&GSprite[0];
  2002.  
  2003.       NumBombs=0;
  2004.       for(UWORD i=1;i<NUMSPRITES;i++) {
  2005.         if(s->active==TRUE && (s->id>=BOMB1 && s->id<=BOMB3)) NumBombs++;
  2006.         s++;
  2007.         }
  2008. }
  2009.  
  2010. //===========================================================================
  2011. // Create enemy functions
  2012. //
  2013. // Main logic for new sprite selection
  2014. // Only selects sprite attributes to appear, counter are set to delay
  2015. // the new sprites appearence and a 'strobe' sprite is created and placed
  2016. // where the new enemy will appear
  2017. //===========================================================================
  2018.  
  2019. inline DWORD RandQuad()
  2020. {
  2021.       DWORD q = rand() & 63;
  2022.  
  2023.     // Give side quadrants more chance because of ratio 8:5
  2024.       if( q<18 ) q = 1;
  2025.       else if( q<36 ) q = 3;
  2026.         else if( q<50 ) q = 0;
  2027.           else q = 2;
  2028.  
  2029.     return( q );
  2030. }
  2031.  
  2032. //---------------------------------------------------------------------------
  2033.  
  2034. inline DWORD RandLine()
  2035. {
  2036.   return( rand() & 3 );
  2037. }
  2038.  
  2039. //---------------------------------------------------------------------------
  2040.  
  2041. BOOL SelectLine( UWORD &q, UWORD &l )
  2042. {
  2043.     DWORD i;
  2044.     UWORD rquad,rline,minl,maxl,quadline,rsl,minw,qd,cposs;
  2045.  
  2046.     // Select random quad & line
  2047.     rquad = RandQuad();
  2048.       if( rquad == GLastQuad ) rquad = (rquad+1) & 3;
  2049.       GLastQuad = rquad;
  2050.       rline = RandLine();
  2051.       quadline = (rquad*4)+rline;
  2052.  
  2053.     //Allow chance to select line with lowest count for distribution spread
  2054.     cposs=rand() & 63;
  2055.       if(cposs < 20) {
  2056.         minl = 99;
  2057.         qd = rquad * 4;
  2058.  
  2059.         for( i=0; i<4; i++ ) {
  2060.             if( GLine[qd+i].count < minl ) {
  2061.                 minl = GLine[qd+i].count;
  2062.                 rline = i;
  2063.                 }
  2064.             }
  2065.           quadline = qd + rline;
  2066.         }
  2067.  
  2068.     if( GLine[quadline].wait != 0 ) {
  2069.         //Look for wait 0
  2070.         rsl = rline;
  2071.         qd = rquad * 4;
  2072.         rline = ( rline + 1 ) & 3;
  2073.         while( rline != rsl ) {
  2074.             if( GLine[qd+rline].wait == 0 ) {
  2075.                 rsl = 99; //Found
  2076.                 break;
  2077.                 }
  2078.             rline = ( rline + 1 ) & 3;
  2079.             }
  2080.  
  2081.         if( rsl != 99 ) { //Free line not found
  2082.             rsl = 99;
  2083.             minw = 999;
  2084.             for ( i=0; i < NUMLINES; i++ ) {
  2085.                 if( GLine[i].wait > 0 && GLine[quadline].wait < minw ) {
  2086.                     minw = GLine[i].wait;
  2087.                     rsl = i;
  2088.                     }
  2089.                 }
  2090.             if( rsl == 99 ) return( FALSE );
  2091.             rquad = rsl >> 2;
  2092.             rline = rsl & 3;
  2093.             }
  2094.         }
  2095.  
  2096.     q = rquad;
  2097.     l = rline;
  2098.  
  2099.     return( TRUE );
  2100. }
  2101.  
  2102. //---------------------------------------------------------------------------
  2103.  
  2104. void CreateStrobe( WORD xpos, WORD ypos )
  2105. {
  2106.     SPRITE *ns;
  2107.  
  2108.     //Create strobe sprite
  2109.       NEWspr=SPRITEGetFree();
  2110.     ns=&GSprite[NEWspr];
  2111.       ns->id=STROBE;
  2112.       ns->line=-1;
  2113.       ns->walk=FALSE;
  2114.       ns->fly=FALSE;
  2115.       ns->oldx=0;
  2116.       ns->oldy=0;
  2117.       ns->xmov=0;
  2118.       ns->ymov=0;
  2119.       ns->x=xpos;
  2120.       ns->y=ypos;
  2121.       ns->active=TRUE;
  2122.       SPRITENewAnim(NEWspr,0,2);
  2123. }
  2124.  
  2125.  
  2126. //---------------------------------------------------------------------------
  2127.  
  2128. void CreateEnemy()
  2129. {
  2130.     UWORD rquad,rline,rcolor,minl,quadline,cposs,i,maxl;
  2131.       WORD  xpos,ypos,mx,my,cx,cy,anm,aspeed,bcolor;
  2132.  
  2133.       if(NEWspr!=-1) return;
  2134.  
  2135.     if( DoingLeadIn ) {  // Initial difficulty creation
  2136.         LineState = BEING_BUILT;
  2137.         rquad = RandQuad();
  2138.           if(rquad==GLastQuad) rquad=(rquad+1) & 3;
  2139.           GLastQuad=rquad;
  2140.           rline = RandLine();
  2141.           quadline=(rquad*4)+rline+1;
  2142.  
  2143.         if(rquad==0 || rquad==2) maxl=3;  //top or bottom - 2
  2144.         else maxl=6; //left or right - 2
  2145.         while(GLine[quadline-1].count >= maxl) {
  2146.             rquad = RandQuad();
  2147.               rline = RandLine();
  2148.               quadline=(rquad*4)+rline+1;
  2149.  
  2150.             if(rquad==0 || rquad==2) maxl=3;  //top or bottom
  2151.             else maxl=6; //left or right
  2152.             }
  2153.         }
  2154.     else {
  2155.         if( SelectLine( rquad, rline ) == FALSE ) return;
  2156.       quadline=(rquad*4)+rline+1;
  2157.         }
  2158.  
  2159.     if(rquad==0 || rquad==2) maxl=5;  //top or bottom
  2160.     else maxl=8; //left or right
  2161.  
  2162.       rcolor=rand() & 3;     //change 3 here for more colors
  2163.       cposs=rand() & 63;
  2164.       // If GColorThreshold is higher there is more chance that color will be same
  2165.       if(cposs<GColorThreshold && GLine[quadline-1].count!=0 && GLine[quadline-1].backcolor<4)
  2166.         rcolor=GLine[quadline-1].backcolor;
  2167.  
  2168.       FindNumBombs();
  2169.       if(((rand() & 63) < 4) && (NumBombs<LevelBombs) && (LastBombQuad!=rquad)) {
  2170.         if(((rand() & 63) < 22) && ((WhichBombs & 1) !=0)) rcolor=BOMB1;
  2171.         else if(((rand() & 63) < 44) && ((WhichBombs & 2) !=0)) rcolor=BOMB2;
  2172.           else if((WhichBombs & 4) !=0) rcolor=BOMB3;
  2173.         LastBombQuad=rquad;
  2174.         }
  2175.  
  2176. //test
  2177.  
  2178.     if( ( rand() & 63 ) < 32 ) rcolor = BOMB1;
  2179.  
  2180. //test
  2181.  
  2182.       // Probability check for bonus letter (don't do if leading in)
  2183.     if(!(DoingLeadIn && (GameMode == CONTINUE))) {
  2184.           if(((rand() & 127)< BonusRand) && ((rand() & 127)< BonusRand)) {
  2185.             if(BonusCount < (5-SpringFull)) rcolor=BONUSB;
  2186.             }
  2187.         }
  2188.  
  2189.     switch(rquad) {
  2190.         case 0:
  2191.             xpos=256+(rline<<5);
  2192.             ypos=0;
  2193.             mx=0; my=2;
  2194.             cx=0; cy=16;
  2195.             anm=AWDOWN;
  2196.             break;
  2197.         case 1:
  2198.             xpos=608;
  2199.             ypos=160+(rline<<5);
  2200.             mx=-2; my=0;
  2201.             cx=16; cy=0;
  2202.             anm=AWLEFT;
  2203.             break;
  2204.         case 2:
  2205.             xpos=256+(rline<<5);
  2206.             ypos=416;
  2207.             mx=0; my=-2;
  2208.             cx=0; cy=16;
  2209.             anm=AWUP;
  2210.             break;
  2211.         case 3:
  2212.             xpos=0;
  2213.             ypos=160+(rline<<5);
  2214.             mx=2; my=0;
  2215.             cx=16; cy=0;
  2216.             anm=AWRIGHT;
  2217.             break;
  2218.         }
  2219.  
  2220.     GLine[quadline-1].wait=5;
  2221.       if(((rquad==0 || rquad==2) && GLine[quadline-1].count==4)
  2222.        || ((rquad==1 || rquad==3) && GLine[quadline-1].count==7)) {
  2223.             GLine[quadline-1].wait = 20;
  2224.             }
  2225.  
  2226.       //Set holdback to higher value if line is full to give player a fighting chance
  2227.     HoldBack=16; HoldLine=-1;
  2228.       if(((rquad==0 || rquad==2) && GLine[quadline-1].count==5)
  2229.        || ((rquad==1 || rquad==3) && GLine[quadline-1].count==8)) {
  2230.             HoldBack = 64;
  2231.             }
  2232.  
  2233.     //Set attributes for this sprite when it appears
  2234.       MOVquadline=quadline;
  2235.       MOVmx=mx; MOVmy=my;
  2236.       MOVcx=cx; MOVcy=cy;
  2237.       MOVanm=anm;
  2238.  
  2239.     if(DoingLeadIn==TRUE) MOVanm-=4;
  2240.  
  2241.       NEWxpos=xpos; NEWypos=ypos;
  2242.       NEWrquad=rquad; NEWrcolor=rcolor;
  2243.       NEWquadline=quadline;
  2244.  
  2245.     CreateStrobe( xpos, ypos );
  2246.  
  2247.     AppearCount=HoldBack+TimeSpeed;
  2248. }
  2249.  
  2250. //---------------------------------------------------------------------------
  2251.  
  2252. // Monitor walking sprites and flag them as stopped walking if necessary
  2253.  
  2254. void MonitorWalking()
  2255. {
  2256.       SPRITE *s;
  2257.       UWORD espr,NWalk=0;
  2258.  
  2259.       s=&GSprite[1];
  2260.       for(UWORD i=1;i<NUMSPRITES;i++) {
  2261.         if(s->active==TRUE && s->walk==TRUE) {
  2262.           if(s->xcnt==0 && s->ycnt==0) {
  2263.                 UWORD rquad=s->quad;
  2264.                 if(rquad==1) rquad=3;
  2265.                 else if(rquad==3) rquad=1;
  2266.                 if(s->id<BONUSB) SPRITENewAnim(i,rquad,1);
  2267.                 else SPRITENewAnim(i,(NET_Game * 5),1);
  2268.                 s->walk=FALSE;
  2269.                 WalkLine=-1;
  2270.                 }
  2271.           }
  2272.         s++;
  2273.         }
  2274. }
  2275.  
  2276. //---------------------------------------------------------------------------
  2277.  
  2278. void NewEnemy()
  2279. {
  2280.       if(MOVquadline!=-1 && AppearCount<16) {
  2281.         MoveLine(MOVquadline,MOVmx,MOVmy,MOVcx,MOVcy,MOVanm);
  2282.         MOVquadline=-1;
  2283.         }
  2284. }
  2285.  
  2286. //---------------------------------------------------------------------------
  2287.  
  2288. void NewInstantEnemy()
  2289. {
  2290.     if(MOVquadline!=-1) {
  2291.         MoveLine(MOVquadline,MOVmx*MOVcx,MOVmy*MOVcy,1,1,MOVanm);
  2292.         MOVquadline=-1;
  2293.         }
  2294. }
  2295.  
  2296. //---------------------------------------------------------------------------
  2297.  
  2298. // Initialise new enemy sprite based on CreateEnemy() attributes
  2299.  
  2300. void EnemyAppear()
  2301. {
  2302.     SPRITE *ne;
  2303.       UWORD espr;
  2304.  
  2305.       if(AppearCount==0) {
  2306.         AppearCount=-1;
  2307.         espr=SPRITEGetFree();
  2308.         ne=&GSprite[espr];
  2309.         ne->active=TRUE;
  2310.         ne->x=NEWxpos;
  2311.         ne->y=NEWypos;
  2312.         ne->quad=NEWrquad;
  2313.         ne->line=NEWquadline;
  2314.         ne->id=NEWrcolor;
  2315.         ne->clag=6;
  2316.         ne->walk=FALSE;
  2317.         ne->fly=FALSE;
  2318.  
  2319.         //if(NEWrcolor < 4) SoundPlay(NEWrcolor);
  2320.  
  2321.         if(NEWrquad==1) NEWrquad=3;
  2322.         else if(NEWrquad==3) NEWrquad=1;
  2323.  
  2324.         if(NEWrcolor<BONUSB) SPRITENewAnim(espr,NEWrquad,1);
  2325.         else SPRITENewAnim(espr,1 + (NET_Game * 5),1);
  2326.         GLine[NEWquadline-1].backcolor=NEWrcolor;
  2327.  
  2328.         if(DoingLeadIn==FALSE) {
  2329.             espr=SPRITEGetFree();
  2330.             ne=&GSprite[espr];
  2331.             ne->id=TWINKLE;
  2332.             ne->line=-1;
  2333.             ne->walk=FALSE;
  2334.             ne->fly=FALSE;
  2335.             ne->oldx=0;
  2336.             ne->oldy=0;
  2337.             ne->xmov=0;
  2338.             ne->ymov=0;
  2339.             ne->x=NEWxpos;
  2340.             ne->y=NEWypos;
  2341.             ne->active=TRUE;
  2342.             SPRITENewAnim(espr,0,0);
  2343.             }
  2344.  
  2345.         //Remove strobe
  2346.         ne=&GSprite[NEWspr];
  2347.         ne->id=0;
  2348.         ne->walk=FALSE;
  2349.         ne->fly=FALSE;
  2350.         ne->line=-1;
  2351.         ne->xmov=0;
  2352.         ne->ymov=0;
  2353.         ne->oldx=0;
  2354.         ne->oldy=0;
  2355.         ne->clag=0;
  2356.         ne->spawnid=-1;
  2357.         ne->active=FALSE;
  2358.         NEWspr=-1;
  2359.         LineState = BUILT;
  2360.         }
  2361.         else {
  2362.         if(AppearCount>0) AppearCount--;
  2363.         }
  2364. }
  2365.  
  2366. //---------------------------------------------------------------------------
  2367.  
  2368. // Return the first sprite number on line 'l'
  2369.  
  2370. UWORD FirstOnLine(UWORD l)
  2371. {
  2372.       SPRITE *s,*e;
  2373.       s=&GSprite[0];
  2374.       e=&GSprite[1];
  2375.       WORD r=(l-1)>>2;
  2376.       WORD mnv,cl;
  2377.       UWORD i;
  2378.  
  2379.       if(GLine[l-1].count==0) return(0);
  2380.       cl=0;
  2381.  
  2382.       switch(r) {
  2383.         case 0:
  2384.           mnv=0;
  2385.           for(i=1;i<NUMSPRITES;i++) {
  2386.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2387.                       if(e->y>=mnv) {
  2388.                         mnv=e->y;
  2389.                         cl=i;
  2390.                         }
  2391.                       }
  2392.                     e++;
  2393.                 }
  2394.           break;
  2395.         case 1:
  2396.           mnv=999;
  2397.           for(i=1;i<NUMSPRITES;i++) {
  2398.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2399.                       if(e->x<=mnv) {
  2400.                        mnv=e->x;
  2401.                         cl=i;
  2402.                         }
  2403.                       }
  2404.                     e++;
  2405.                 }
  2406.           break;
  2407.         case 2:
  2408.           mnv=999;
  2409.           for(i=1;i<NUMSPRITES;i++) {
  2410.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2411.                       if(e->y<=mnv) {
  2412.                         mnv=e->y;
  2413.                         cl=i;
  2414.                         }
  2415.                       }
  2416.                     e++;
  2417.                 }
  2418.           break;
  2419.         case 3:
  2420.           mnv=0;
  2421.           for(i=1;i<NUMSPRITES;i++) {
  2422.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2423.                       if(e->x>=mnv) {
  2424.                         mnv=e->x;
  2425.                         cl=i;
  2426.                         }
  2427.                       }
  2428.                   e++;
  2429.                 }
  2430.           break;
  2431.         }
  2432.  
  2433.       return(cl);
  2434. }
  2435.  
  2436. //---------------------------------------------------------------------------
  2437.  
  2438. // Return the last sprite number on line 'l'
  2439.  
  2440. UWORD LastOnLine(UWORD l)
  2441. {
  2442.       SPRITE *s,*e;
  2443.       s=&GSprite[0];
  2444.       e=&GSprite[1];
  2445.       WORD r=(l-1)>>2;
  2446.       WORD mnv,cl;
  2447.       UWORD i;
  2448.  
  2449.       if(GLine[l-1].count==0) return(0);
  2450.       cl=0;
  2451.  
  2452.       switch(r) {
  2453.         case 0:
  2454.           mnv=999;
  2455.           for(i=1;i<NUMSPRITES;i++) {
  2456.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2457.                       if(e->y<=mnv) {
  2458.                         mnv=e->y;
  2459.                         cl=i;
  2460.                         }
  2461.                       }
  2462.                     e++;
  2463.                 }
  2464.           break;
  2465.         case 1:
  2466.           mnv=0;
  2467.           for(i=1;i<NUMSPRITES;i++) {
  2468.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2469.                       if(e->x>=mnv) {
  2470.                        mnv=e->x;
  2471.                         cl=i;
  2472.                         }
  2473.                       }
  2474.                     e++;
  2475.                 }
  2476.           break;
  2477.         case 2:
  2478.           mnv=0;
  2479.           for(i=1;i<NUMSPRITES;i++) {
  2480.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2481.                       if(e->y>=mnv) {
  2482.                         mnv=e->y;
  2483.                         cl=i;
  2484.                         }
  2485.                       }
  2486.                     e++;
  2487.                 }
  2488.           break;
  2489.         case 3:
  2490.           mnv=999;
  2491.           for(i=1;i<NUMSPRITES;i++) {
  2492.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2493.                       if(e->x<=mnv) {
  2494.                         mnv=e->x;
  2495.                         cl=i;
  2496.                         }
  2497.                       }
  2498.                   e++;
  2499.                 }
  2500.           break;
  2501.         }
  2502.       return(cl);
  2503. }
  2504.  
  2505.  
  2506. //---------------------------------------------------------------------------
  2507.  
  2508. // Return sprite number that player has collided with (or 0 if none)
  2509.  
  2510. UWORD CheckCollision(UWORD l,WORD xoff,WORD yoff)
  2511. {
  2512.       SPRITE *s,*e,*hit;
  2513.       s=&GSprite[0];
  2514.       e=&GSprite[1];
  2515.       WORD sx=s->x+xoff,sy=s->y+yoff;
  2516.       WORD sxx=sx+32,syy=sy+32;
  2517.       WORD r=(l-1)>>2;
  2518.       WORD mnv,cl;
  2519.       UWORD i;
  2520.  
  2521.       if(GLine[l-1].count==0) return(0);
  2522.       cl=0;
  2523.  
  2524.       switch(r) {
  2525.         case 0:
  2526.           mnv=0;
  2527.           for(i=1;i<NUMSPRITES;i++) {
  2528.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2529.                       if(e->y>=mnv) {
  2530.                         mnv=e->y;
  2531.                         hit=e;
  2532.                         cl=i;
  2533.                         }
  2534.                       }
  2535.                     e++;
  2536.                 }
  2537.           break;
  2538.         case 1:
  2539.           mnv=999;
  2540.           for(i=1;i<NUMSPRITES;i++) {
  2541.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2542.                       if(e->x<=mnv) {
  2543.                        mnv=e->x;
  2544.                         hit=e;
  2545.                         cl=i;
  2546.                         }
  2547.                       }
  2548.                     e++;
  2549.                 }
  2550.           break;
  2551.         case 2:
  2552.           mnv=999;
  2553.           for(i=1;i<NUMSPRITES;i++) {
  2554.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2555.                       if(e->y<=mnv) {
  2556.                         mnv=e->y;
  2557.                         hit=e;
  2558.                         cl=i;
  2559.                         }
  2560.                       }
  2561.                     e++;
  2562.                 }
  2563.           break;
  2564.         case 3:
  2565.           mnv=0;
  2566.           for(i=1;i<NUMSPRITES;i++) {
  2567.                 if(e->active==TRUE && (e->id<EXPLODE || (e->id==BONUSB)) && e->line==l) {
  2568.                       if(e->x>=mnv) {
  2569.                         mnv=e->x;
  2570.                         hit=e;
  2571.                         cl=i;
  2572.                         }
  2573.                       }
  2574.                   e++;
  2575.                 }
  2576.           break;
  2577.         }
  2578.  
  2579.       e=hit;
  2580.       if(!((sxx < e->x) || (sx > e->x+32) || (syy < e->y) || (sy > e->y+32))) return(cl);
  2581.       return(0);
  2582. }
  2583.  
  2584. //---------------------------------------------------------------------------
  2585.  
  2586. // Check for enemy sprites walking into centre square (end of game)
  2587.  
  2588. BOOL GCheckGameOver()
  2589. {
  2590.       BOOL gover=FALSE,KillSp;
  2591.     DWORD maxl;
  2592.     SPRITE *s;
  2593.  
  2594.       Strobe=FALSE;
  2595.  
  2596.       s=&GSprite[1];
  2597.       for(UWORD i=1;i<NUMSPRITES;i++) {
  2598.         if( s->active ) {
  2599.             //Middle square breached
  2600.             if( s->id<EXPLODE ) {
  2601.               if(s->quad==0 && s->y==160) gover=TRUE;
  2602.               if(s->quad==1 && s->x==352) gover=TRUE;
  2603.               if(s->quad==2 && s->y==256) gover=TRUE;
  2604.               if(s->quad==3 && s->x==256) gover=TRUE;
  2605.               }
  2606.             //Check for killer touching middle square
  2607.           if(s->quad==0 || s->quad==2 ) maxl = 5;
  2608.             else maxl = 8;
  2609.  
  2610.             if( s->id<PCOLOR1 && GLine[s->line-1].count == maxl ) {
  2611.               if(s->quad==0 && s->y==160-32) Strobe=TRUE;
  2612.               if(s->quad==1 && s->x==352+32) Strobe=TRUE;
  2613.               if(s->quad==2 && s->y==256+32) Strobe=TRUE;
  2614.               if(s->quad==3 && s->x==256-32) Strobe=TRUE;
  2615.               }
  2616.             }
  2617.         s++;
  2618.         }
  2619.  
  2620.       if(Strobe==TRUE) {
  2621.         LineState = WILL_KILL;
  2622.         StrobeSound--;
  2623.         if(StrobeSound<0) {
  2624.             SoundPlay(5); // this needs to on another channel
  2625.             StrobeSound=40;
  2626.             }
  2627.         SPal(StrobeColor1,StrobeVal1+=4,0,0);
  2628.         GPalette[StrobeColor1*3]=StrobeVal1-4;
  2629.         if(StrobeColor1!=StrobeColor2) {
  2630.             SPal(StrobeColor2,StrobeVal2+=4,0,0);
  2631.             GPalette[StrobeColor2*3]=StrobeVal2-4;
  2632.             }
  2633.         }
  2634.       else {
  2635.         if( LineState = WILL_KILL ) LineState = BEING_BUILT;
  2636.  
  2637.         StrobeVal1=0;
  2638.         SPal(StrobeColor1,StrobeR1,StrobeG1,StrobeB1);
  2639.         StrobeVal2=0;
  2640.         SPal(StrobeColor2,StrobeR1,StrobeG2,StrobeB2);
  2641.         StrobeSound=0;
  2642.         }
  2643.  
  2644.       return(gover);
  2645. }
  2646.  
  2647. //---------------------------------------------------------------------------
  2648. // Bonus 5000 and 10000 functions
  2649. //---------------------------------------------------------------------------
  2650.  
  2651. void SetStar(WORD x,WORD y,WORD dx,WORD dy)
  2652. {
  2653.     UWORD snew;
  2654.     SPRITE *s;
  2655.  
  2656.     snew=SPRITEGetFree();
  2657.  
  2658.     s=&GSprite[snew];
  2659.     s->active=TRUE;
  2660.     s->id=LINEBONUS;
  2661.     s->x=x; s->y=y;
  2662.     s->fly=TRUE;
  2663.       s->dline=SPRLINE;
  2664.       s->sline=2;
  2665.       s->pline=5;
  2666.       s->clag=65000;
  2667.       s->update=TRUE;
  2668.     SPRITENewAnim(snew,4,0);
  2669.       WorkoutLine(s,s->x,s->y,dx,dy);
  2670. }
  2671.  
  2672. //---------------------------------------------------------------------------
  2673.  
  2674. void Bonus5000()
  2675. {
  2676.     UWORD snew;
  2677.     SPRITE *s;
  2678.  
  2679.     GBScore+=5000;
  2680.  
  2681.     snew=SPRITEGetFree();
  2682.     s=&GSprite[snew];
  2683.     s->active=TRUE;
  2684.     s->id=LINEBONUS;
  2685.     s->x=288; s->y=208;
  2686.     SPRITENewAnim(snew,2,0);
  2687.  
  2688.     snew=SPRITEGetFree();
  2689.     s=&GSprite[snew];
  2690.     s->active=TRUE;
  2691.     s->id=LINEBONUS;
  2692.     s->x=288+32; s->y=208;
  2693.     SPRITENewAnim(snew,3,0);
  2694.  
  2695.     SetStar(256,208,256-48,208);
  2696.     SetStar(352,208,352+48,208);
  2697.  
  2698.     SetStar(272+8,176+8,(272-48)+12,(176-48)+12);
  2699.     SetStar(272+8,240-8,(272-48)+12,(240+48)-12);
  2700.  
  2701.     SetStar(304,176,304,176-48);
  2702.     SetStar(304,240,304,240+48);
  2703.  
  2704.     SetStar(336-8,176+8,(336+48)-12,(176-48)+12);
  2705.     SetStar(336-8,240-8,(336+48)-12,(240+48)-12);
  2706.     SoundPlay(10);
  2707. }
  2708.  
  2709. //---------------------------------------------------------------------------
  2710.  
  2711. void Bonus10000()
  2712. {
  2713.     UWORD snew;
  2714.     SPRITE *s;
  2715.  
  2716.     GBScore+=10000;
  2717.  
  2718.     snew=SPRITEGetFree();
  2719.     s=&GSprite[snew];
  2720.     s->active=TRUE;
  2721.     s->id=LINEBONUS;
  2722.     s->x=288; s->y=208;
  2723.     SPRITENewAnim(snew,0,0);
  2724.  
  2725.     snew=SPRITEGetFree();
  2726.     s=&GSprite[snew];
  2727.     s->active=TRUE;
  2728.     s->id=LINEBONUS;
  2729.     s->x=288+32; s->y=208;
  2730.     SPRITENewAnim(snew,1,0);
  2731.  
  2732.     SetStar(256,208,256-48,208);
  2733.     SetStar(352,208,352+48,208);
  2734.  
  2735.     SetStar(272+8,176+8,(272-48)+12,(176-48)+12);
  2736.     SetStar(272+8,240-8,(272-48)+12,(240+48)-12);
  2737.  
  2738.     SetStar(304,176,304,176-48);
  2739.     SetStar(304,240,304,240+48);
  2740.  
  2741.     SetStar(336-8,176+8,(336+48)-12,(176-48)+12);
  2742.     SetStar(336-8,240-8,(336+48)-12,(240+48)-12);
  2743.     SoundPlay(10);
  2744. }
  2745.  
  2746.  
  2747. //---------------------------------------------------------------------------
  2748.  
  2749. // Create a score sprite based on current line accumulation and fly it
  2750.  
  2751. void ScoreFly(WORD x,WORD y)
  2752. {
  2753.     SPRITE *fl;
  2754.     UWORD FlyScr;
  2755.  
  2756.     if(DetailLevel>0) return;
  2757.  
  2758.     FlyScr=SPRITEGetFree();
  2759.     fl=&GSprite[FlyScr];
  2760.       fl->id=SCORE100+Accum-1;
  2761.       fl->walk=FALSE;
  2762.       fl->fly=TRUE;
  2763.       fl->line=-1;
  2764.       fl->xmov=0;
  2765.       fl->ymov=0;
  2766.       fl->oldx=0;
  2767.       fl->oldy=0;
  2768.       fl->dline=SPRLINEKILL;
  2769.       fl->sline=1;
  2770.       fl->pline=10;
  2771.       fl->clag=65000;
  2772.       fl->active=TRUE;
  2773.       fl->update=TRUE;
  2774.       fl->x=x;
  2775.       fl->y=y;
  2776.       WorkoutLine(&GSprite[FlyScr],GSprite[FlyScr].x,GSprite[FlyScr].y,176,40);
  2777.       SPRITENewAnim(FlyScr,0,0);
  2778. }
  2779.  
  2780. //---------------------------------------------------------------------------
  2781.  
  2782. // Pause game option
  2783.  
  2784. BOOL CheckPause()
  2785. {
  2786.     if( NET_Game != 0 ) return( FALSE );
  2787.  
  2788.     if( KEY[K_PAUSE] == TRUE ) return( TRUE );
  2789.     return( FALSE );
  2790. }
  2791.  
  2792. //---------------------------------------------------------------------------
  2793.  
  2794. void Event_Pause()
  2795. {
  2796.       UWORD p[10],i;
  2797.     SPRITE *s;
  2798.     UWORD *prisave;
  2799.     void GControlPlayer();
  2800.  
  2801.     if( ! EVENT_Pause ) return;
  2802.     if( GPlayerMode != INMIDDLE ) return;
  2803.  
  2804.       while(GPlayerMode!=INMIDDLE) {
  2805.         GRAPHICUpdate();
  2806.         GControlPlayer();
  2807.         }
  2808.  
  2809.     FireEnableStatus=FALSE;
  2810.  
  2811.     while( WalkLine != -1 ) {
  2812.       GControlPlayer();
  2813.        MonitorWalking();
  2814.         PANELUpdate();
  2815.         GRAPHICUpdate();
  2816.         }
  2817.  
  2818.     for(i=0;i<10;i++) {
  2819.         p[i]=SPRITEGetFree();
  2820.         GSprite[p[i]].active=TRUE;
  2821.         GSprite[p[i]].id=PAUSED;
  2822.         GSprite[p[i]].xmov=0;
  2823.         GSprite[p[i]].ymov=0;
  2824.         GSprite[p[i]].oldx=0;
  2825.         GSprite[p[i]].oldy=0;
  2826.  
  2827.         if(i<5) {
  2828.           GSprite[p[i]].x=240+(i*32);
  2829.           GSprite[p[i]].y=192;
  2830.           }
  2831.         else {
  2832.           GSprite[p[i]].x=240+((i-5)*32);
  2833.           GSprite[p[i]].y=192+32;
  2834.           }
  2835.  
  2836.         SPRITENewAnim(p[i],i,0);
  2837.         }
  2838.  
  2839.     SetPauseTime();
  2840.  
  2841.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  2842.  
  2843.     // Save priorities
  2844.     prisave = new UWORD[NUMSPRITES];
  2845.     s = &GSprite[0];
  2846.     for( i=0; i<NUMSPRITES; i++ ) {
  2847.         prisave[i] = s->pri;
  2848.         if( s->active == TRUE && (s->id < DIGIT0 || s->id == BONUSB || (s->id > DIGIT9 && s->id < BONUSB ) ) ) {
  2849.             s->pri = 99; //Not visible
  2850.             s->forcedupdate = TRUE;
  2851.             }
  2852.         s++;
  2853.         }
  2854.  
  2855.     GRAPHICUpdate();
  2856.       GRAPHICUpdate();
  2857.  
  2858.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  2859.  
  2860.     GRAPHICUpdate();
  2861.       GRAPHICUpdate();
  2862.       while(CheckPause()==TRUE);
  2863.  
  2864.       while(CheckPause()!=TRUE) {
  2865.         WaitTimer();
  2866.         NET_Update();
  2867.         }
  2868.       while(CheckPause()==TRUE) {
  2869.         WaitTimer();
  2870.         NET_Update();
  2871.         }
  2872.  
  2873.       for(i=0;i<10;i++) {
  2874.        SPRITENewAnim(p[i],10,0); //Kill it
  2875.         }
  2876.       GRAPHICUpdate();
  2877.       GRAPHICUpdate();
  2878.  
  2879.     // Restore priorities
  2880.     s = &GSprite[0];
  2881.     for( i=0; i<NUMSPRITES; i++ ) {
  2882.         s->pri = prisave[i];
  2883.         s->forcedupdate = TRUE;
  2884.         s++;
  2885.         }
  2886.     delete prisave;
  2887.  
  2888.       GRAPHICUpdate();
  2889.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  2890.  
  2891.     GRAPHICUpdate();
  2892.  
  2893.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  2894.  
  2895.     ModifyGameClock();
  2896.  
  2897.     FireEnableStatus=TRUE;
  2898.     EVENT_Pause = FALSE;
  2899. }
  2900.  
  2901. //---------------------------------------------------------------------------
  2902.  
  2903. //--New code: Standard box collision 11/9 jj----------------
  2904.  
  2905. inline BOOL BoxCol( DWORD b1xl, DWORD b1yl, DWORD b1xh, DWORD b1yh, DWORD b2xl, DWORD b2yl, DWORD b2xh, DWORD b2yh )
  2906. {
  2907.     if( b1yl > b2yh ) return( FALSE );
  2908.     if( b1yh < b2yl ) return( FALSE );
  2909.     if( b1xl > b2xh ) return( FALSE );
  2910.     if( b1xh < b2xl ) return( FALSE );
  2911.  
  2912.     return( TRUE );
  2913. }
  2914.  
  2915. //---------------------------------------------------------------------------
  2916.  
  2917. // Bomb1 - Area bomb, destroys upto 9 enemies surrounding it.
  2918. // Also, if bomb1 hits other bomb1's they blow up also!
  2919.  
  2920. //--New code: ExplodeBomb generally optimized and debugged 11/9 jj-----------
  2921.  
  2922. void ExplodeBomb1(WORD sx,WORD sy)
  2923. {
  2924.       void BonusRegister(UWORD,UWORD);
  2925.       SPRITE *s,*e;
  2926.       s=&GSprite[0];
  2927.       e=&GSprite[1];
  2928.       BOOL EXP;
  2929.  
  2930.       WORD behind;
  2931.       WORD ex,ey,exx,eyy;
  2932.  
  2933.     DWORD b1yl, b1xl, b1yh, b1xh, b2yl, b2xl, b2yh, b2xh;
  2934.  
  2935.     b1yl = sy - 20; b1yh = b1yl + 70;
  2936.     b1xl = sx - 20; b1xh = b1xl + 70;
  2937.  
  2938.       for(UWORD i=1;i<NUMSPRITES;i++) {
  2939.          if((e->active == TRUE) && (e->fly == FALSE) && ( ( e->id < EXPLODE ) || ( e->id == BONUSB ) ) ) {
  2940.           EXP=FALSE;
  2941.           ex=e->x; ey=e->y; exx=e->x+32; eyy=e->y+32;
  2942.  
  2943.             EXP = BoxCol( b1xl, b1yl, b1xh, b1yh, ex, ey, exx, eyy );
  2944.  
  2945.           if(EXP==TRUE) {
  2946.                   if(e->id==BOMB1) {
  2947.                     e->id=EXPLODE;
  2948.                     ExplodeBomb1(ex,ey);
  2949.                     }
  2950.                 if(e->id==BONUSB) {
  2951.                   BonusRegister(e->x,e->y);
  2952.                   }
  2953.                 Kills--;
  2954.                 GBKills++;
  2955.                 TotalKills++;
  2956.                 Accum=1;
  2957.                 ScoreFly(e->x,e->y);
  2958.                 GBScore+=100;
  2959.                 e->id=EXPLODE;
  2960.                 e->walk=FALSE;
  2961.                 e->oldx=0;
  2962.                 e->oldy=0;
  2963.                 e->xmov=0;
  2964.                 e->ymov=0;
  2965.                 SPRITENewAnim(i,0,0);
  2966.                 LastLineKill=e->line;
  2967.                 if(e->line==HoldLine) {
  2968.                     if(AppearCount > 16) AppearCount=16;
  2969.                     }
  2970.  
  2971.                 e->line=-1;
  2972.                 }
  2973.           }
  2974.         e++;
  2975.         }
  2976. }
  2977.  
  2978. //---------------------------------------------------------------------------
  2979.  
  2980. // Bomb2 - Line bomb, destroys entire line regardless of colors
  2981.  
  2982. void ExplodeBomb2(WORD cl)
  2983. {
  2984.       void BonusRegister(UWORD,UWORD);
  2985.       SPRITE *e;
  2986.       e=&GSprite[cl];
  2987.  
  2988.       if(e->id==BONUSB) {
  2989.         BonusRegister(e->x,e->y);
  2990.         }
  2991.       Kills--;
  2992.       GBKills++;
  2993.     TotalKills++;
  2994.       LastBombKill=e->id;
  2995.  
  2996.       Accum=1;
  2997.  
  2998.       //Check for color accumulation
  2999.       UWORD q=e->quad;
  3000.    LastKill=e->id;
  3001.    LastLineKill=e->line;
  3002.    ScoreFly(e->x,e->y);
  3003.    e->id=EXPLODE;
  3004.    e->walk=FALSE;
  3005.    e->oldx=0;
  3006.    e->oldy=0;
  3007.    e->xmov=0;
  3008.    e->ymov=0;
  3009.    SPRITENewAnim(cl,0,0);
  3010.    GBScore+=100;
  3011.  
  3012.     if(e->line==HoldLine) {
  3013.         if(AppearCount > 16) AppearCount=16;
  3014.         }
  3015.  
  3016.     e->line=-1;
  3017. }
  3018.  
  3019. //---------------------------------------------------------------------------
  3020.  
  3021. // Bomb3 - Color bomb, destroys all enemies in quadrant with same color
  3022. // as the enemy that this bomb first hits.
  3023.  
  3024. void ExplodeBomb3(WORD q,WORD id)
  3025. {
  3026.       SPRITE *e;
  3027.       e=&GSprite[1];
  3028.  
  3029.       UWORD ex,ey;
  3030.  
  3031.       for(UWORD i=1;i<NUMSPRITES;i++) {
  3032.         if(e->active==TRUE && (e->id==id && e->quad==q)) {
  3033.           if(e->id==BOMB1 || e->id==BOMB2 || e->id==BOMB3) {
  3034.                 if(e->id==BOMB1) {
  3035.                       e->id=0;
  3036.                       ex=e->x; ey=e->y;
  3037.                       ExplodeBomb1(ex,ey);
  3038.                       }
  3039.                 }
  3040.           Kills--;
  3041.           GBKills++;
  3042.             TotalKills++;
  3043.           Accum=1;
  3044.           ScoreFly(e->x,e->y);
  3045.           e->id=EXPLODE;
  3046.           e->walk=FALSE;
  3047.           e->oldx=0;
  3048.           e->oldy=0;
  3049.           e->xmov=0;
  3050.           e->ymov=0;
  3051.           SPRITENewAnim(i,0,0);
  3052.           GBScore+=100;
  3053.           LastLineKill=e->line;
  3054.             if(e->line==HoldLine) {
  3055.                 if(AppearCount > 16) AppearCount=16;
  3056.                 }
  3057.           e->line=-1;
  3058.           }
  3059.         e++;
  3060.         }
  3061. }
  3062.  
  3063. //===========================================================================
  3064. // Add Block functions
  3065. //===========================================================================
  3066.  
  3067. void AddBlockToLine( DWORD rcolor, DWORD rquad, DWORD rline )
  3068. {
  3069.     DWORD i,j,k;
  3070.     DWORD LineCount,CurrLine;
  3071.     WORD Spr,SNew,mx,my,cx,cy,Cline,xpos,ypos;
  3072.     BOOL DoneSound;
  3073.     SPRITE *s;
  3074.  
  3075.     Cline = rquad*4 + rline;
  3076.  
  3077.     if(Cline<4) {
  3078.         xpos=256+(rline<<5);
  3079.         ypos=0;
  3080.         mx=0; my=32;
  3081.         }
  3082.     if(Cline>3 && Cline<8) {
  3083.         xpos=608;
  3084.         ypos=160+(rline<<5);
  3085.         mx=-32; my=0;
  3086.         }
  3087.     if(Cline>7 && Cline<12) {
  3088.         xpos=256+(rline<<5);
  3089.         ypos=416;
  3090.         mx=0; my=-32;
  3091.         //Cline=11-(Cline-8);
  3092.         }
  3093.     if(Cline>11) {
  3094.         xpos=0;
  3095.         ypos=160+(rline<<5);
  3096.         mx=32; my=0;
  3097.         //Cline=15-(Cline-12);
  3098.         }
  3099.  
  3100.     FindLineCount();
  3101.  
  3102.     Spr = FirstOnLine(Cline+1);
  3103.  
  3104.     if( Spr != 0 ) {
  3105.         xpos = GSprite[Spr].x + mx;
  3106.         ypos = GSprite[Spr].y + my;
  3107.         }
  3108.  
  3109.    SNew = SPRITEGetFree();
  3110.     s=&GSprite[SNew];
  3111.    s->active=TRUE;
  3112.    s->x = xpos;
  3113.    s->y = ypos;
  3114.    s->quad = rquad;
  3115.    s->line = Cline + 1;
  3116.    s->id=rcolor;
  3117.    s->clag=6;
  3118.    s->walk=FALSE;
  3119.    s->fly=FALSE;
  3120.  
  3121.    if(rquad==1) rquad=3;
  3122.    else if(rquad==3) rquad=1;
  3123.    SPRITENewAnim(SNew,rquad,1);
  3124. }
  3125.  
  3126. //---------------------------------------------------------------------------
  3127.  
  3128. void NETShowReceived( DWORD Target )
  3129. {
  3130.     UWORD spr;
  3131.     SPRITE *s;
  3132.  
  3133.     spr = SPRITEGetFree();
  3134.     s = &GSprite[ spr ];
  3135.      s->id = NETCROSS + Target;
  3136.      s->line=-1;
  3137.      s->walk=FALSE;
  3138.      s->fly=FALSE;
  3139.      s->oldx=0;
  3140.      s->oldy=0;
  3141.      s->xmov=0;
  3142.      s->ymov=0;
  3143.      s->x = 464;
  3144.      s->y = 368;
  3145.      s->active=TRUE;
  3146.      SPRITENewAnim( spr,4,0 );
  3147.  
  3148.     spr = SPRITEGetFree();
  3149.     s = &GSprite[ spr ];
  3150.      s->id = NETCROSS + Target;
  3151.      s->line=-1;
  3152.      s->walk=FALSE;
  3153.      s->fly=FALSE;
  3154.      s->oldx=0;
  3155.      s->oldy=0;
  3156.      s->xmov=0;
  3157.      s->ymov=0;
  3158.      s->x = 464+32;
  3159.      s->y = 368;
  3160.      s->active=TRUE;
  3161.      SPRITENewAnim( spr,5,0 );
  3162.  
  3163.     spr = SPRITEGetFree();
  3164.     s = &GSprite[ spr ];
  3165.      s->id = NETCROSS + Target;
  3166.      s->line=-1;
  3167.      s->walk=FALSE;
  3168.      s->fly=FALSE;
  3169.      s->oldx=0;
  3170.      s->oldy=0;
  3171.      s->xmov=0;
  3172.      s->ymov=0;
  3173.      s->x = 464;
  3174.      s->y = 368+32;
  3175.      s->active=TRUE;
  3176.      SPRITENewAnim( spr,6,0 );
  3177.  
  3178.     spr = SPRITEGetFree();
  3179.     s = &GSprite[ spr ];
  3180.      s->id = NETCROSS + Target;
  3181.      s->line=-1;
  3182.      s->walk=FALSE;
  3183.      s->fly=FALSE;
  3184.      s->oldx=0;
  3185.      s->oldy=0;
  3186.      s->xmov=0;
  3187.      s->ymov=0;
  3188.      s->x = 464+32;
  3189.      s->y = 368+32;
  3190.      s->active=TRUE;
  3191.      SPRITENewAnim( spr,7,0 );
  3192. }
  3193.  
  3194. //---------------------------------------------------------------------------
  3195.  
  3196. void AddBlock( DWORD rcolor, DWORD nblocks )
  3197. {
  3198.       void GControlPlayer();
  3199.       void ScoreTrack();
  3200.       void KillsTrack();
  3201.     DWORD q,r,l,maxl,i,j;
  3202.  
  3203.       SPRITE *s;
  3204.       UWORD b,zc;
  3205.       BOOL DoKill, DoFly, FoundLine;
  3206.  
  3207.     if( GPlayerMode != INMIDDLE ) return;
  3208.     if( LineState == BEING_BUILT ) return;
  3209.  
  3210.     NETShowReceived( 0 );
  3211.  
  3212.     FireEnableStatus=FALSE;
  3213.  
  3214.     for( i=0; i<32; i++ ) {
  3215.       GControlPlayer();
  3216.        MonitorWalking();
  3217.         PANELUpdate();
  3218.         GRAPHICUpdate();
  3219.         }
  3220.  
  3221.       // Wait for beam to terminate
  3222.       DoKill=TRUE;
  3223.       while(DoKill==TRUE) {
  3224.       GControlPlayer();
  3225.         PANELUpdate();
  3226.         GRAPHICUpdate();
  3227.         DoKill=FALSE;
  3228.         for(i=1;i<NUMSPRITES;i++) {
  3229.           if((GSprite[i].active==TRUE) && (GSprite[i].id==LIGHTBEAM)) DoKill=TRUE;
  3230.           }
  3231.         }
  3232.  
  3233.     // Wait for flying sprites to finish
  3234.       DoFly=TRUE;
  3235.       while(DoFly==TRUE) {
  3236.       GControlPlayer();
  3237.         PANELUpdate();
  3238.         GRAPHICUpdate();
  3239.         DoFly=FALSE;
  3240.         for(i=1;i<NUMSPRITES;i++) {
  3241.           if((GSprite[i].active==TRUE) && (GSprite[i].dline!=NOLINE)) DoFly=TRUE;
  3242.           }
  3243.         }
  3244.  
  3245.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  3246.  
  3247.     for( i=0; i<nblocks; i++ ) {
  3248.         FindLineCount();
  3249.  
  3250.         q = RandQuad();
  3251.         r = RandLine();
  3252.         l = q*4 + r;
  3253.         if( q == 0 || q == 2 ) maxl = 3;  //top or bottom
  3254.         else maxl = 6; //left or right
  3255.  
  3256.         FoundLine = TRUE;
  3257.         if( GLine[ l ].count >= maxl ) {  //Line to full for additions
  3258.             FoundLine = FALSE;
  3259.             for( j=l+1; j!=l; j = (j+1) & 15 ) {
  3260.                 q = j / 4;
  3261.                 r = j % 4;
  3262.                 if( q == 0 || q == 2 ) maxl = 3;  //top or bottom
  3263.                 else maxl = 6; //left or right
  3264.  
  3265.                 if( GLine[ j ].count < maxl ) {
  3266.                     FoundLine = TRUE;
  3267.                     break;  //Found room in line
  3268.                     }
  3269.                 }
  3270.             if( j == l ) {
  3271.                 FoundLine = FALSE;
  3272.                 break;  //No room left
  3273.                 }
  3274.             }
  3275.  
  3276.         if( FoundLine ) AddBlockToLine( rcolor, q, r );
  3277.         }
  3278.  
  3279.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  3280.  
  3281.     FireEnableStatus=TRUE;
  3282.  
  3283.     EVENT_AddBlock--;
  3284. }
  3285.  
  3286. //---------------------------------------------------------------------------
  3287.  
  3288. void Event_AddBlock()
  3289. {
  3290.     if( EVENT_AddBlock > 0 ) {
  3291.         BlockAddColor = ( rand() & 3 );
  3292.         AddBlock( BlockAddColor, BlockAddAmount );
  3293.         }
  3294. }
  3295.  
  3296. //===========================================================================
  3297. // Bonus event functions
  3298. //===========================================================================
  3299.  
  3300. void SpringSetup()
  3301. {
  3302.       for(UWORD i=0;i<5;i++)
  3303.         Spring[i]=0;
  3304. }
  3305.  
  3306. //---------------------------------------------------------------------------
  3307.  
  3308. // Check if bonus is complete and if so, initiate enemy clear sequence
  3309.  
  3310. void DoSingleBonus()
  3311. {
  3312.       void GControlPlayer();
  3313.       void ScoreTrack();
  3314.       void KillsTrack();
  3315.     DWORD SoundPause;
  3316.       SPRITE *s;
  3317.       UWORD b,i,zc;
  3318.       BOOL DoKill, DoFly;
  3319.  
  3320.     if( GPlayerMode != INMIDDLE ) return;
  3321.     if( LineState == BEING_BUILT ) return;
  3322.  
  3323.     FireEnableStatus=FALSE;
  3324.  
  3325.     for( i=0; i<32; i++ ) {
  3326.       GControlPlayer();
  3327.        MonitorWalking();
  3328.         PANELUpdate();
  3329.         GRAPHICUpdate();
  3330.         }
  3331.  
  3332.       // Wait for beam to terminate
  3333.       DoKill=TRUE;
  3334.       while(DoKill==TRUE) {
  3335.       GControlPlayer();
  3336.         PANELUpdate();
  3337.         GRAPHICUpdate();
  3338.         DoKill=FALSE;
  3339.         for(i=1;i<NUMSPRITES;i++) {
  3340.           if((GSprite[i].active==TRUE) && (GSprite[i].id==LIGHTBEAM)) DoKill=TRUE;
  3341.           }
  3342.         }
  3343.  
  3344.     // Wait for flying sprites to finish
  3345.       DoFly=TRUE;
  3346.       while(DoFly==TRUE) {
  3347.       GControlPlayer();
  3348.         PANELUpdate();
  3349.         GRAPHICUpdate();
  3350.         DoFly=FALSE;
  3351.         for(i=1;i<NUMSPRITES;i++) {
  3352.           if((GSprite[i].active==TRUE) && (GSprite[i].dline!=NOLINE)) DoFly=TRUE;
  3353.           }
  3354.         }
  3355.  
  3356.       for(i=0;i<5;i++) {
  3357.         SPRITENewAnim(Spring[i],3 + (NET_Game*5),1);
  3358.         }
  3359.  
  3360.     //--New code: Remove strobe 8/9 jj-------------------------------------------
  3361.     if( NEWspr != -1 )
  3362.     {
  3363.         s = &GSprite[ NEWspr ];
  3364.  
  3365.         s->id=0;
  3366.         s->walk=FALSE;
  3367.         s->fly=FALSE;
  3368.         s->line=-1;
  3369.         s->xmov=0;
  3370.         s->ymov=0;
  3371.         s->oldx=0;
  3372.         s->oldy=0;
  3373.         s->clag=0;
  3374.         s->spawnid=-1;
  3375.         s->active=FALSE;
  3376.         NEWspr=-1;
  3377.         LineState = BUILT;
  3378.  
  3379.         AppearCount = 0;
  3380.     }
  3381.     //---------------------------------------------------------------------------
  3382.  
  3383.  
  3384.       for(i=0;i<30;i++) {
  3385.         PANELUpdate();
  3386.         GRAPHICUpdate();
  3387.         }
  3388.     SoundPause=1;
  3389.  
  3390.       GBScore+=10000;
  3391.  
  3392.       GSprite[0].animtog=FALSE;
  3393.  
  3394.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  3395.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  3396.  
  3397.       UWORD lk;
  3398.       UWORD Sel[NUMSPRITES];
  3399.       UWORD NSel;
  3400.       UBYTE r1,r2;
  3401.  
  3402.       r1=rand() & 0xff;
  3403.       while (r1==0) r1=rand() & 0xff;
  3404.       r2=rand() & 16;
  3405.       while (r2==0) r2=rand() & 16;
  3406.  
  3407.       NSel=1;
  3408.       while(NSel!=0) {
  3409.         NSel=0;
  3410.         s=&GSprite[1];
  3411.         for(i=1;i<NUMSPRITES;i++) {
  3412.           if(s->active==TRUE && (s->id<EXPLODE)) {
  3413.                 Sel[NSel++]=i;
  3414.                 }
  3415.           s++;
  3416.           }
  3417.         if(NSel!=0) {
  3418.           r1+=r2;
  3419.           lk=r1 & 0xff;
  3420.           while(lk>=NSel) lk=0;
  3421.           lk=Sel[lk];
  3422.  
  3423.           Kills--;
  3424.           GBKills++;
  3425.             TotalKills++;
  3426.           s=&GSprite[lk];
  3427.           s->id=EXPLODE;
  3428.           s->walk=FALSE;
  3429.           s->oldx=0;
  3430.           s->oldy=0;
  3431.           s->xmov=0;
  3432.           s->ymov=0;
  3433.           SPRITENewAnim(lk,0,0);
  3434.           s->animtime=2;
  3435.           GBScore+=100;
  3436.             SoundPause--;
  3437.             if(SoundPause<1) {
  3438.                 SoundPlay(10);
  3439.                 SoundPause=2;
  3440.                 }
  3441.           for(i=0;i<3;i++) {
  3442.                 PANELUpdate();
  3443.                 GRAPHICUpdate();
  3444.                 }
  3445.           }
  3446.         }
  3447.       for(i=0;i<16;i++) {
  3448.         PANELUpdate();
  3449.         GRAPHICUpdate();
  3450.         }
  3451.  
  3452.       BOOL DoScup=TRUE;
  3453.  
  3454.       while(DoScup==TRUE) {
  3455.         PANELUpdate();
  3456.         GRAPHICUpdate();
  3457.         for(i=0;i<7;i++) {
  3458.           if(GSprite[Score[i]].animtog==TRUE) DoScup=TRUE;
  3459.           else DoScup=FALSE;
  3460.           }
  3461.         }
  3462.  
  3463.       LastKill=0;
  3464.       LastLineKill=0;
  3465.  
  3466.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  3467.       GMorphPal(0,255,6,(UBYTE *) BackPcx.palette);
  3468.  
  3469.       for(i=0;i<5;i++) {
  3470.         GSprite[Spring[i]].id=BONUSB;
  3471.         SPRITENewAnim(Spring[i],4 + (NET_Game * 5),1);
  3472.         PANELUpdate();
  3473.         GRAPHICUpdate();
  3474.         PANELUpdate();
  3475.         GRAPHICUpdate();
  3476.         PANELUpdate();
  3477.         GRAPHICUpdate();
  3478.         }
  3479.  
  3480.     for(i=0;i<30;i++) {
  3481.         PANELUpdate();
  3482.         GRAPHICUpdate();
  3483.         }
  3484.  
  3485.       SpringSetup();
  3486.       SpringFull=0;
  3487.  
  3488.     if( Kills < 1 ) LineState = BUILT;  // This will enable instant trigger of next level sequence
  3489.     else LineState = BEING_BUILT;
  3490.  
  3491.     AppearCount = 0;
  3492.  
  3493.     FireEnableStatus=TRUE;
  3494.  
  3495.     EVENT_Bonus--;
  3496. }
  3497.  
  3498. //---------------------------------------------------------------------------
  3499.  
  3500. void NETMergeTargets()
  3501. {
  3502.       SPRITE *s;
  3503.       UWORD i;
  3504.  
  3505.     //Check for flying springs
  3506.     for( i=0; i<5; i++ )
  3507.     {
  3508.         s = &GSprite[ SpringMerge[ i ] ];
  3509.         if( s->dline != NOLINE ) return;
  3510.     }
  3511.  
  3512.     s = &GSprite[ SpringMerge[0] ];
  3513.     s->fly=TRUE;
  3514.       s->dline=SPRLINE;
  3515.       s->sline=1;
  3516.       s->pline=20;
  3517.       WorkoutLine( s, s->x, s->y, s->x + 64, s->y );
  3518.     if(DetailLevel==0) {
  3519.         s->spawnid=TRAIL;
  3520.           s->spawntime=2;
  3521.           s->spawncnt=2;
  3522.         }
  3523.     else s->spawnid=-1;
  3524.  
  3525.     s = &GSprite[ SpringMerge[1] ];
  3526.     s->fly=TRUE;
  3527.       s->dline=SPRLINE;
  3528.       s->sline=1;
  3529.       s->pline=10;
  3530.       WorkoutLine( s, s->x, s->y, s->x + 32, s->y );
  3531.     if(DetailLevel==0) {
  3532.         s->spawnid=TRAIL;
  3533.           s->spawntime=2;
  3534.           s->spawncnt=2;
  3535.         }
  3536.     else s->spawnid=-1;
  3537.  
  3538.     s = &GSprite[ SpringMerge[4] ];
  3539.     s->fly=TRUE;
  3540.       s->dline=SPRLINE;
  3541.       s->sline=1;
  3542.       s->pline=20;
  3543.       WorkoutLine( s, s->x, s->y, s->x - 64, s->y );
  3544.     if(DetailLevel==0) {
  3545.         s->spawnid=TRAIL;
  3546.           s->spawntime=2;
  3547.           s->spawncnt=2;
  3548.         }
  3549.     else s->spawnid=-1;
  3550.  
  3551.     s = &GSprite[ SpringMerge[3] ];
  3552.     s->fly=TRUE;
  3553.       s->dline=SPRLINE;
  3554.       s->sline=1;
  3555.       s->pline=10;
  3556.       WorkoutLine( s, s->x, s->y, s->x - 32, s->y );
  3557.     if(DetailLevel==0) {
  3558.         s->spawnid=TRAIL;
  3559.           s->spawntime=2;
  3560.           s->spawncnt=2;
  3561.         }
  3562.     else s->spawnid=-1;
  3563.  
  3564.     NETSEQUENCE++;
  3565.     NETSEQUENCECOUNT = 60;
  3566. }
  3567.  
  3568. //---------------------------------------------------------------------------
  3569.  
  3570. DWORD MidSprite;
  3571.  
  3572. void NETChooseType()
  3573. {
  3574.     SPRITE *s;
  3575.     DWORD r,spr,i;
  3576.  
  3577.     if( NETSEQUENCECOUNT != 0 ) {
  3578.         NETSEQUENCECOUNT--;
  3579.         return;
  3580.         }
  3581.  
  3582.       for(i=0;i<5;i++) {
  3583.         GSprite[SpringMerge[i]].id=BONUSB;
  3584.         SPRITENewAnim(SpringMerge[i],4 + (NET_Game * 5),1);
  3585.         }
  3586.  
  3587.     r = rand() & 31;
  3588.     if( r < 11 ) r = 0;
  3589.     else {
  3590.         if( r < 21 ) r = 1;
  3591.           else r = 2;
  3592.         }
  3593.  
  3594.     spr = SPRITEGetFree();
  3595.     s = &GSprite[ spr ];
  3596.      s->id = NETCROSSFLASH + r;
  3597.      s->line=-1;
  3598.      s->walk=FALSE;
  3599.      s->fly=FALSE;
  3600.      s->oldx=0;
  3601.      s->oldy=0;
  3602.      s->xmov=0;
  3603.      s->ymov=0;
  3604.      s->x = 64;
  3605.      s->y = 384;
  3606.      s->active=TRUE;
  3607.      SPRITENewAnim( spr,0,0 );
  3608.  
  3609.     s = &GSprite[ SpringMerge[ 2 ] ];
  3610.     s->active = FALSE;
  3611.  
  3612.     MidSprite = spr;
  3613.  
  3614.     NETTARGETTYPE = r;
  3615.  
  3616.     NETSEQUENCE++;
  3617.     NETSEQUENCECOUNT = 80;
  3618. }
  3619.  
  3620. //---------------------------------------------------------------------------
  3621.  
  3622. void NETChooseSend()
  3623. {
  3624.     UWORD spr;
  3625.     SPRITE *s;
  3626.  
  3627.     if( NETSEQUENCECOUNT != 0 ) {
  3628.         NETSEQUENCECOUNT--;
  3629.         return;
  3630.         }
  3631.  
  3632.      SPRITENewAnim( MidSprite,1,0 );
  3633.  
  3634.     spr = SPRITEGetFree();
  3635.     s = &GSprite[ spr ];
  3636.      s->id = NETCROSS + NETTARGETTYPE;
  3637.      s->line=-1;
  3638.      s->walk=FALSE;
  3639.      s->fly=FALSE;
  3640.      s->oldx=0;
  3641.      s->oldy=0;
  3642.      s->xmov=0;
  3643.      s->ymov=0;
  3644.      s->x = 48;
  3645.      s->y = 368;
  3646.      s->active=TRUE;
  3647.      SPRITENewAnim( spr,0,0 );
  3648.  
  3649.     spr = SPRITEGetFree();
  3650.     s = &GSprite[ spr ];
  3651.      s->id = NETCROSS + NETTARGETTYPE;
  3652.      s->line=-1;
  3653.      s->walk=FALSE;
  3654.      s->fly=FALSE;
  3655.      s->oldx=0;
  3656.      s->oldy=0;
  3657.      s->xmov=0;
  3658.      s->ymov=0;
  3659.      s->x = 48+32;
  3660.      s->y = 368;
  3661.      s->active=TRUE;
  3662.      SPRITENewAnim( spr,1,0 );
  3663.  
  3664.     spr = SPRITEGetFree();
  3665.     s = &GSprite[ spr ];
  3666.      s->id = NETCROSS + NETTARGETTYPE;
  3667.      s->line=-1;
  3668.      s->walk=FALSE;
  3669.      s->fly=FALSE;
  3670.      s->oldx=0;
  3671.      s->oldy=0;
  3672.      s->xmov=0;
  3673.      s->ymov=0;
  3674.      s->x = 48;
  3675.      s->y = 368+32;
  3676.      s->active=TRUE;
  3677.      SPRITENewAnim( spr,2,0 );
  3678.  
  3679.     spr = SPRITEGetFree();
  3680.     s = &GSprite[ spr ];
  3681.      s->id = NETCROSS + NETTARGETTYPE;
  3682.      s->line=-1;
  3683.      s->walk=FALSE;
  3684.      s->fly=FALSE;
  3685.      s->oldx=0;
  3686.      s->oldy=0;
  3687.      s->xmov=0;
  3688.      s->ymov=0;
  3689.      s->x = 48+32;
  3690.      s->y = 368+32;
  3691.      s->active=TRUE;
  3692.      SPRITENewAnim( spr,3,0 );
  3693.  
  3694.     NETSEQUENCE++;
  3695.     NETSEQUENCECOUNT = 60;
  3696. }
  3697.  
  3698. //---------------------------------------------------------------------------
  3699.  
  3700. void NETSendArrows( DWORD send )
  3701. {
  3702.     DWORD pos, xp;
  3703.     UWORD spr;
  3704.     SPRITE *s,*fs;
  3705.  
  3706.     pos = ( send + 1 ) * 5;
  3707.     xp = NET_Name_Posx[ pos ];
  3708.  
  3709.     spr = SPRITEGetFree();
  3710.     s = &GSprite[ spr ];
  3711.      s->id = NETFONT;
  3712.      s->line=-1;
  3713.      s->walk=FALSE;
  3714.      s->fly=FALSE;
  3715.      s->oldx=0;
  3716.      s->oldy=0;
  3717.      s->xmov=0;
  3718.      s->ymov=0;
  3719.     s->x = xp - 16;
  3720.      s->y = 448;
  3721.      s->active=TRUE;
  3722.      SPRITENewAnim( spr, 49, 0 );
  3723.  
  3724.     spr = SPRITEGetFree();
  3725.     s = &GSprite[ spr ];
  3726.      s->id = NETFONT;
  3727.      s->line=-1;
  3728.      s->walk=FALSE;
  3729.      s->fly=FALSE;
  3730.      s->oldx=0;
  3731.      s->oldy=0;
  3732.      s->xmov=0;
  3733.      s->ymov=0;
  3734.     s->x = xp + ( 16 * 5 );
  3735.      s->y = 448;
  3736.      s->active=TRUE;
  3737.      SPRITENewAnim( spr, 48, 0 );
  3738. }
  3739.  
  3740. //---------------------------------------------------------------------------
  3741.  
  3742. void NETReceiveArrows( DWORD send )
  3743. {
  3744.     DWORD pos, xp;
  3745.     UWORD spr;
  3746.     SPRITE *s,*fs;
  3747.  
  3748.     pos = ( send + 1 ) * 5;
  3749.     xp = NET_Name_Posx[ pos ];
  3750.  
  3751.     spr = SPRITEGetFree();
  3752.     s = &GSprite[ spr ];
  3753.      s->id = NETFONT;
  3754.      s->line=-1;
  3755.      s->walk=FALSE;
  3756.      s->fly=FALSE;
  3757.      s->oldx=0;
  3758.      s->oldy=0;
  3759.      s->xmov=0;
  3760.      s->ymov=0;
  3761.     s->x = xp - 32;
  3762.      s->y = 448;
  3763.      s->active=TRUE;
  3764.      SPRITENewAnim( spr, 48, 0 );
  3765.  
  3766.     spr = SPRITEGetFree();
  3767.     s = &GSprite[ spr ];
  3768.      s->id = NETFONT;
  3769.      s->line=-1;
  3770.      s->walk=FALSE;
  3771.      s->fly=FALSE;
  3772.      s->oldx=0;
  3773.      s->oldy=0;
  3774.      s->xmov=0;
  3775.      s->ymov=0;
  3776.     s->x = xp + ( 16 * 5 ) + 16;
  3777.      s->y = 448;
  3778.      s->active=TRUE;
  3779.      SPRITENewAnim( spr, 49, 0 );
  3780. }
  3781.  
  3782. //---------------------------------------------------------------------------
  3783.  
  3784. void NETSendToPlayer()
  3785. {
  3786.     DWORD Send;
  3787.  
  3788.     if( NETSEQUENCECOUNT != 0 ) {
  3789.         NETSEQUENCECOUNT--;
  3790.         return;
  3791.         }
  3792.  
  3793.     Send = NETRandomPlayer();
  3794.  
  3795.     if( Send != -1 ) {
  3796.         NETSendArrows( Send );
  3797.         NETSendEvent( Send, 'A' + NETTARGETTYPE, 8 ); //Block count will also go here
  3798.         }
  3799.  
  3800.     NETSEQUENCE++;
  3801. }
  3802.  
  3803. //---------------------------------------------------------------------------
  3804.  
  3805. void DoNetBonus()
  3806. {
  3807.       void GControlPlayer();
  3808.       void ScoreTrack();
  3809.       void KillsTrack();
  3810.     DWORD SoundPause;
  3811.       SPRITE *s;
  3812.       UWORD b,i,zc;
  3813.       BOOL DoKill, DoFly;
  3814.  
  3815.     switch( NETSEQUENCE )
  3816.     {
  3817.         case 0:
  3818.             NETMergeTargets();
  3819.             break;
  3820.         case 1:
  3821.             NETChooseType();
  3822.             break;
  3823.         case 2:
  3824.             NETChooseSend();
  3825.             break;
  3826.         case 3:
  3827.             NETSendToPlayer();
  3828.             break;
  3829.         case 4:
  3830.             if( NETSEQUENCECOUNT == 0 ) {
  3831.                 EVENT_Bonus--;
  3832.                 }
  3833.             else NETSEQUENCECOUNT--;
  3834.             break;
  3835.     }
  3836. }
  3837.  
  3838. //---------------------------------------------------------------------------
  3839.  
  3840. void DoBlowUpBonus()
  3841. {
  3842.       void GControlPlayer();
  3843.       void ScoreTrack();
  3844.       void KillsTrack();
  3845.     DWORD SoundPause;
  3846.       SPRITE *s;
  3847.       UWORD b,i,zc;
  3848.       BOOL DoKill, DoFly;
  3849.  
  3850.     if( GPlayerMode != INMIDDLE ) return;
  3851.     if( LineState == BEING_BUILT ) return;
  3852.  
  3853.     NETShowReceived( 1 );
  3854.  
  3855.     FireEnableStatus=FALSE;
  3856.  
  3857.     for( i=0; i<32; i++ ) {
  3858.       GControlPlayer();
  3859.        MonitorWalking();
  3860.         PANELUpdate();
  3861.         GRAPHICUpdate();
  3862.         }
  3863.  
  3864.       // Wait for beam to terminate
  3865.       DoKill=TRUE;
  3866.       while(DoKill==TRUE) {
  3867.       GControlPlayer();
  3868.         PANELUpdate();
  3869.         GRAPHICUpdate();
  3870.         DoKill=FALSE;
  3871.         for(i=1;i<NUMSPRITES;i++) {
  3872.           if((GSprite[i].active==TRUE) && (GSprite[i].id==LIGHTBEAM)) DoKill=TRUE;
  3873.           }
  3874.         }
  3875.  
  3876.     // Wait for flying sprites to finish
  3877.       DoFly=TRUE;
  3878.       while(DoFly==TRUE) {
  3879.       GControlPlayer();
  3880.         PANELUpdate();
  3881.         GRAPHICUpdate();
  3882.         DoFly=FALSE;
  3883.         for(i=1;i<NUMSPRITES;i++) {
  3884.           if((GSprite[i].active==TRUE) && (GSprite[i].dline!=NOLINE)) DoFly=TRUE;
  3885.           }
  3886.         }
  3887.  
  3888.       for(i=0;i<30;i++) {
  3889.         PANELUpdate();
  3890.         GRAPHICUpdate();
  3891.         }
  3892.     SoundPause=1;
  3893.  
  3894.       GBScore+=10000;
  3895.  
  3896.       GSprite[0].animtog=FALSE;
  3897.  
  3898.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  3899.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  3900.  
  3901.       UWORD lk;
  3902.       UWORD Sel[NUMSPRITES];
  3903.       UWORD NSel;
  3904.       UBYTE r1,r2;
  3905.  
  3906.       r1=rand() & 0xff;
  3907.       while (r1==0) r1=rand() & 0xff;
  3908.       r2=rand() & 16;
  3909.       while (r2==0) r2=rand() & 16;
  3910.  
  3911.       NSel=1;
  3912.       while(NSel!=0) {
  3913.         NSel=0;
  3914.         s=&GSprite[1];
  3915.         for(i=1;i<NUMSPRITES;i++) {
  3916.           if(s->active==TRUE && (s->id<EXPLODE || s->id==BONUSB)) {
  3917.                 Sel[NSel++]=i;
  3918.                 }
  3919.           s++;
  3920.           }
  3921.         if(NSel!=0) {
  3922.           r1+=r2;
  3923.           lk=r1 & 0xff;
  3924.           while(lk>=NSel) lk=0;
  3925.           lk=Sel[lk];
  3926.  
  3927.           Kills--;
  3928.           GBKills++;
  3929.             TotalKills++;
  3930.           s=&GSprite[lk];
  3931.           s->id=EXPLODE;
  3932.           s->walk=FALSE;
  3933.           s->oldx=0;
  3934.           s->oldy=0;
  3935.           s->xmov=0;
  3936.           s->ymov=0;
  3937.           SPRITENewAnim(lk,0,0);
  3938.           s->animtime=2;
  3939.           GBScore+=100;
  3940.             SoundPause--;
  3941.             if(SoundPause<1) {
  3942.                 SoundPlay(10);
  3943.                 SoundPause=2;
  3944.                 }
  3945.           for(i=0;i<3;i++) {
  3946.                 PANELUpdate();
  3947.                 GRAPHICUpdate();
  3948.                 }
  3949.           }
  3950.         }
  3951.       for(i=0;i<16;i++) {
  3952.         PANELUpdate();
  3953.         GRAPHICUpdate();
  3954.         }
  3955.  
  3956.       BOOL DoScup=TRUE;
  3957.  
  3958.       while(DoScup==TRUE) {
  3959.         PANELUpdate();
  3960.         GRAPHICUpdate();
  3961.         for(i=0;i<7;i++) {
  3962.           if(GSprite[Score[i]].animtog==TRUE) DoScup=TRUE;
  3963.           else DoScup=FALSE;
  3964.           }
  3965.         }
  3966.  
  3967.       LastKill=0;
  3968.       LastLineKill=0;
  3969.  
  3970.       GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  3971.       GMorphPal(0,255,6,(UBYTE *) BackPcx.palette);
  3972.  
  3973.     if( Kills < 1 ) LineState = BUILT;  // This will enable instant trigger of next level sequence
  3974.     else LineState = BEING_BUILT;
  3975.  
  3976.     AppearCount = 0;
  3977.  
  3978.     FireEnableStatus=TRUE;
  3979.  
  3980.     EVENT_BlowUp--;
  3981. }
  3982.  
  3983. //---------------------------------------------------------------------------
  3984.  
  3985. void DoAddTarget()
  3986. {
  3987.     SPRITE *rs;
  3988.       UWORD fs, i;
  3989.  
  3990.     for( i=0; i<SpringFull; i++ )
  3991.     {
  3992.         rs = &GSprite[ Spring[ i ] ];
  3993.         if( rs->dline != NOLINE ) return;
  3994.     }
  3995.  
  3996.     SoundPlay(9);
  3997.  
  3998.       fs=SPRITEGetFree();
  3999.     rs=&GSprite[fs];
  4000.  
  4001.     rs->id=BONUSO;
  4002.       rs->walk=FALSE;
  4003.       rs->line=-1;
  4004.       rs->xmov=0;
  4005.       rs->ymov=0;
  4006.       rs->oldx=0;
  4007.       rs->oldy=0;
  4008.       rs->active=TRUE;
  4009.       rs->update=TRUE;
  4010.       rs->clag=65000;
  4011.       rs->fly=FALSE;
  4012.       rs->x=SpringFull*32;
  4013.       rs->y=12*32;
  4014.     rs->spawnid=-1;
  4015.  
  4016.       SPRITENewAnim(fs,(NET_Game * 5)+1,0);
  4017.  
  4018.     Spring[SpringFull]=fs;
  4019.       SpringFull++;
  4020.  
  4021.       fs=SPRITEGetFree();
  4022.     rs=&GSprite[fs];
  4023.  
  4024.     rs->id=TRAIL;
  4025.       rs->walk=FALSE;
  4026.       rs->line=-1;
  4027.       rs->xmov=0;
  4028.       rs->ymov=0;
  4029.       rs->oldx=0;
  4030.       rs->oldy=0;
  4031.       rs->active=TRUE;
  4032.       rs->update=TRUE;
  4033.       rs->clag=65000;
  4034.       rs->fly=FALSE;
  4035.       rs->x=(SpringFull-1)*32;
  4036.       rs->y=12*32;
  4037.     rs->spawnid=-1;
  4038.  
  4039.       SPRITENewAnim(fs,0,0);
  4040.  
  4041.       if(SpringFull >= 5) {
  4042.         for( i=0; i<5; i++ ) {
  4043.             rs = &GSprite[ Spring[ i ] ];
  4044.             if( rs->dline != SPRLINE ) {
  4045.                 rs->id = EXPLODE;
  4046.                   SPRITENewAnim( Spring[i],0,0 );
  4047.                 SpringFull--;
  4048.                 }
  4049.             }
  4050.         }
  4051.     EVENT_AddTarget--;
  4052. }
  4053.  
  4054. //---------------------------------------------------------------------------
  4055.  
  4056. void Event_BlowUp()
  4057. {
  4058.     if( EVENT_BlowUp != 0 ) DoBlowUpBonus();
  4059. }
  4060.  
  4061. //---------------------------------------------------------------------------
  4062.  
  4063. void Event_AddTarget()
  4064. {
  4065.     if( EVENT_AddTarget != 0 ) DoAddTarget();
  4066. }
  4067.  
  4068. //---------------------------------------------------------------------------
  4069.  
  4070. void Event_Bonus()
  4071. {
  4072.     if( EVENT_Bonus != 0 ) {
  4073.         if( NET_Game == 0 ) DoSingleBonus();
  4074.         else DoNetBonus();
  4075.         }
  4076. }
  4077.  
  4078. //===========================================================================
  4079. // SpeedUp event functions
  4080. //===========================================================================
  4081.  
  4082. void DoSpeedUp()
  4083. {
  4084.     SpeedUpDuration--;
  4085.     if( SpeedUpDuration == 0 ) TimeSpeed = OldSpeed;
  4086. }
  4087.  
  4088. //---------------------------------------------------------------------------
  4089.  
  4090. void Event_SpeedUp()
  4091. {
  4092.     if( EVENT_SpeedUp != 0 && SpeedUpDuration == 0 ) {
  4093.         NETShowReceived( 2 );
  4094.         SpeedUpDuration = 300;
  4095.         OldSpeed = TimeSpeed;
  4096.         TimeSpeed = 1;
  4097.         EVENT_SpeedUp--;
  4098.         }
  4099.     if( SpeedUpDuration != 0 ) DoSpeedUp();
  4100. }
  4101.  
  4102. //===========================================================================
  4103. // Register collection of bonus spring
  4104. //===========================================================================
  4105.  
  4106. void BonusRegister(UWORD x,UWORD y)
  4107. {
  4108.     SPRITE *rs;
  4109.       UWORD fs,i;
  4110.  
  4111.     SoundPlay(9);
  4112.  
  4113.       fs=SPRITEGetFree();
  4114.     rs=&GSprite[fs];
  4115.  
  4116.       //Set letter to fly
  4117.     rs->id=BONUSO;
  4118.       rs->walk=FALSE;
  4119.       rs->line=-1;
  4120.       rs->xmov=0;
  4121.       rs->ymov=0;
  4122.       rs->oldx=0;
  4123.       rs->oldy=0;
  4124.       rs->active=TRUE;
  4125.       rs->update=TRUE;
  4126.       rs->dline=SPRLINE;
  4127.       rs->sline=1;
  4128.       rs->pline=0;
  4129.       rs->clag=65000;
  4130.       rs->fly=TRUE;
  4131.       rs->x=x;
  4132.       rs->y=y;
  4133.  
  4134.     if(DetailLevel==0) {
  4135.         rs->spawnid=TRAIL;
  4136.           rs->spawntime=2;
  4137.           rs->spawncnt=2;
  4138.         }
  4139.     else rs->spawnid=-1;
  4140.  
  4141.     WorkoutLine(rs,x,y,(SpringFull*32),(12*32));
  4142.       SPRITENewAnim(fs,(NET_Game * 5),0);
  4143.  
  4144.     Spring[SpringFull]=fs;
  4145.       SpringFull++;
  4146.  
  4147.       if(SpringFull == 5) {
  4148.         NETSEQUENCE = 0;
  4149.         EVENT_Bonus++;
  4150.         for( i=0; i<5; i++ ) {
  4151.             SpringMerge[ i ] = Spring[ i ];
  4152.             }
  4153.         SpringFull = 0;
  4154.         }
  4155.  
  4156.     NETSendAllPlayers( 'D', 0 );
  4157. }
  4158.  
  4159. //===========================================================================
  4160. // Player functions
  4161. //===========================================================================
  4162.  
  4163. // Check player collisions, deals with colors,bombs and line bonus
  4164.  
  4165. UWORD GPlayerCollision()
  4166. {
  4167.       UWORD cl;
  4168.       WORD HitSpr;
  4169.     SPRITE *pl=&GSprite[0],*hit;
  4170.  
  4171.       DoBeam=TRUE;
  4172.  
  4173.       switch(GPlayerFacing) {
  4174.         case FACEUP:
  4175.           cl=CheckCollision(GPlayerRunLine,0,-4);
  4176.           break;
  4177.         case FACEDOWN:
  4178.            cl=CheckCollision(GPlayerRunLine,0,4);
  4179.           break;
  4180.         case FACELEFT:
  4181.           cl=CheckCollision(GPlayerRunLine,-4,0);
  4182.           break;
  4183.         case FACERIGHT:
  4184.           cl=CheckCollision(GPlayerRunLine,4,0);
  4185.           break;
  4186.         }
  4187.       if(cl!=0 && GSprite[cl].id==BONUSB) {
  4188.         Accum=1;
  4189.         GBScore+=100;
  4190.         LastKill=-1;
  4191.         Kills--;
  4192.         GBKills++;
  4193.         TotalKills++;
  4194.         BonusRegister(GSprite[cl].x,GSprite[cl].y);
  4195. //--New code: Spring now creates 100 sprite 12/9 jj----------------
  4196.         hit=&GSprite[cl];
  4197.         ScoreFly(hit->x,hit->y);
  4198.         hit->id=0;
  4199.         hit->active=FALSE;
  4200.         hit->line=-1;
  4201.         hit->walk=FALSE;
  4202.         hit->oldx=0;
  4203.         hit->oldy=0;
  4204.         hit->xmov=0;
  4205.         hit->ymov=0;
  4206.         cl=0;
  4207.         }
  4208.  
  4209.       if(cl!=0) {
  4210.         UWORD PID=pl->id;
  4211.  
  4212.         if(PID>=PCOLOR1 && PID<=PCOLOR4) PID-=PCOLOR1;
  4213.         if(GSprite[cl].id!=PID || pl->id==BOMB1 || pl->id==BOMB2 || pl->id==BOMB3) {
  4214.           UWORD rquad=GSprite[cl].quad;
  4215.  
  4216. //--New code: Also added pl->id != BOMB1 because BOMB1 now kills hit icon 11/9 jj----------------
  4217.           if(GSprite[cl].id<=COLOR4 && GSprite[cl].id!=PID && pl->id!=BOMB2 && pl->id != BOMB1 ) {
  4218.                 HitSpr=SPRITEGetFree();
  4219.                 hit=&GSprite[HitSpr];
  4220.                 hit->id=COLORHIT1+GSprite[cl].id;
  4221.                 hit->walk=FALSE;
  4222.                 hit->fly=FALSE;
  4223.                 hit->line=-1;
  4224.                 hit->xmov=0;
  4225.                 hit->ymov=0;
  4226.                 hit->oldx=0;
  4227.                 hit->oldy=0;
  4228.                 hit->active=TRUE;
  4229.                 hit->update=TRUE;
  4230.                 hit->x=GSprite[cl].x;
  4231.                 hit->y=GSprite[cl].y;
  4232.                 SPRITENewAnim(HitSpr,0,0);
  4233.                 if(rquad==0) GSprite[HitSpr].y+=16;
  4234.                 if(rquad==1) GSprite[HitSpr].x-=16;
  4235.                 if(rquad==2) GSprite[HitSpr].y-=16;
  4236.                 if(rquad==3) GSprite[HitSpr].x+=16;
  4237.                 }
  4238.  
  4239.           if(GSprite[cl].clag==0) { // Swap colors with sprite hit
  4240.                 UWORD tid=GSprite[cl].id;
  4241.                 GSprite[cl].id=PID;
  4242.                 pl->id=tid;
  4243.                 if(tid<BOMB1) pl->id+=PCOLOR1;
  4244.                 PID=tid;
  4245.  
  4246. //--Additional code: Do not generate bomb collect sound if hit with bomb2(linebomb) 12/9 jj----------------
  4247.                 if(PID==BOMB1 && GSprite[cl].id != BOMB2 ) SoundPlay(8);
  4248.                 if(PID==BOMB2) SoundPlay(7);
  4249.                 if(PID==BOMB3 && GSprite[cl].id != BOMB2 ) SoundPlay(6);
  4250.                 }
  4251.  
  4252.           if(GSprite[cl].id==BOMB1) {
  4253.                 SoundPlay(10);
  4254.                 GSprite[cl].id=0;
  4255.                 ExplodeBomb1(GSprite[cl].x,GSprite[cl].y);
  4256.                 }
  4257.           if(GSprite[cl].id==BOMB2) {
  4258.                 if(Bomb2Sound!=TRUE) {
  4259.                     SoundPlay(10);
  4260.                     Bomb2Sound=TRUE;
  4261.                     }
  4262.                 GSprite[cl].id=PID;
  4263.                 pl->id=BOMB2;
  4264.                 ExplodeBomb2(cl);
  4265.                 cl=0;
  4266.                 }
  4267.           if(GSprite[cl].id==BOMB3) {
  4268.                 SoundPlay(10);
  4269.                 GSprite[cl].id=PID;
  4270.                 ExplodeBomb3(GSprite[cl].quad,PID);
  4271.                 }
  4272.           if(GSprite[cl].id<=COLOR4) {
  4273.                 //SoundPlay(7);
  4274.                 if(rquad==1) rquad=3;
  4275.                 else if(rquad==3) rquad=1;
  4276.                 SPRITENewAnim(cl,rquad,1);
  4277.                 }
  4278.  
  4279.  
  4280.  
  4281.           }
  4282.         else {
  4283.           if(GSprite[cl].id==LastKill && GSprite[cl].line==LastLineKill) {
  4284.                 Accum++;
  4285.                 }
  4286.           else {
  4287.                 Accum=1;
  4288.                 }
  4289.             //if(GPlayerRunLine==HoldLine) AppearCount=16+TimeSpeed;
  4290.  
  4291.             //Create fly score sprite here
  4292.           ScoreFly(GSprite[cl].x,GSprite[cl].y);
  4293.           GBScore+=100*Accum;
  4294.           LastKill=GSprite[cl].id;
  4295.           LastLineKill=GSprite[cl].line;
  4296.           Kills--;
  4297.           GBKills++;
  4298.             TotalKills++;
  4299.           UWORD q=GSprite[cl].quad;
  4300.             SPRITE *Bon;
  4301.             //Check accumulated line for single color clearence
  4302.             Bon=&GSprite[cl];
  4303.           if(((q==0 || q==2) && Accum==5) || ((q==1 || q==3) && Accum==8)) {
  4304.                 if(Accum==5) Bonus5000();
  4305.                 else Bonus10000();
  4306.                 }
  4307.             Bon->id=0;
  4308.             Bon->active=FALSE;
  4309.           Bon->line=-1;
  4310.           Bon->walk=FALSE;
  4311.           Bon->oldx=0;
  4312.           Bon->oldy=0;
  4313.           Bon->xmov=0;
  4314.           Bon->ymov=0;
  4315.  
  4316.           DoBeam=FALSE;
  4317.           cl=0;
  4318.           }
  4319.         }
  4320.  
  4321.     return(cl);
  4322. }
  4323.  
  4324. //---------------------------------------------------------------------------
  4325.  
  4326. // Player feedback (direction and firing)
  4327.  
  4328. #define PLAYERUP        1
  4329. #define PLAYERDOWN    2
  4330. #define PLAYERLEFT    3
  4331. #define PLAYERRIGHT    4
  4332.  
  4333. DWORD JoyLastDir;
  4334. DWORD JoyLastMov;
  4335.  
  4336. void JoystickResponse( UWORD *d, BOOL *f )
  4337. {
  4338.     DWORD jx, jy;
  4339.  
  4340.     jx = jy = 0;
  4341.  
  4342.     if( Joy.JOY1x < ( JoyNormalx - (JoyNormalx/4) ) ) jx = -1;
  4343.     if( Joy.JOY1x > ( JoyNormalx + (JoyNormalx/4) ) ) jx = 1;
  4344.     if( Joy.JOY1y < ( JoyNormaly - (JoyNormaly/4) ) ) jy = -1;
  4345.     if( Joy.JOY1y > ( JoyNormaly + (JoyNormaly/4) ) ) jy = 1;
  4346.  
  4347.     if( (Joy.JOYd1 & JOYafire) == JOYafire ) *f = TRUE;
  4348.     else *f=FALSE;
  4349.  
  4350.     //Continual direction check
  4351.     if( jx == 1 && JoyLastMov == PLAYERRIGHT ) {
  4352.         *d = PLAYERRIGHT;
  4353.         return;
  4354.         }
  4355.  
  4356.     if( jx == -1 && JoyLastMov == PLAYERLEFT ) {
  4357.         *d = PLAYERLEFT;
  4358.         return;
  4359.         }
  4360.  
  4361.     if( jy == 1 && JoyLastMov == PLAYERDOWN ) {
  4362.         *d = PLAYERDOWN;
  4363.         return;
  4364.         }
  4365.  
  4366.     if( jy == -1 && JoyLastMov == PLAYERUP ) {
  4367.         *d = PLAYERUP;
  4368.         return;
  4369.         }
  4370.  
  4371.     //Diagonal check
  4372.     if( jx != 0 && jy != 0 ) {
  4373.         switch( JoyLastMov ) {
  4374.             case PLAYERUP:
  4375.                 if( jx == -1 ) *d = PLAYERLEFT;
  4376.                 if( jx == 1 ) *d = PLAYERRIGHT;
  4377.                 break;
  4378.             case PLAYERDOWN:
  4379.                 if( jx == -1 ) *d = PLAYERLEFT;
  4380.                 if( jx == 1 ) *d = PLAYERRIGHT;
  4381.                 break;
  4382.             case PLAYERLEFT:
  4383.                 if( jy == -1 ) *d = PLAYERUP;
  4384.                 if( jy == 1 ) *d = PLAYERDOWN;
  4385.                 break;
  4386.             case PLAYERRIGHT:
  4387.                 if( jy == -1 ) *d = PLAYERUP;
  4388.                 if( jy == 1 ) *d = PLAYERDOWN;
  4389.                 break;
  4390.             }
  4391.         JoyLastMov = *d;
  4392.         return;
  4393.         }
  4394.  
  4395.     //Directional movement
  4396.     if( jx == -1 ) *d = PLAYERLEFT;
  4397.     if( jx == 1 ) *d = PLAYERRIGHT;
  4398.     if( jy == -1 ) *d = PLAYERUP;
  4399.     if( jy == 1 ) *d = PLAYERDOWN;
  4400.  
  4401.     if( *d != 0) JoyLastMov = *d;
  4402. }
  4403.  
  4404. //---------------------------------------------------------------------------
  4405.  
  4406. void MOUSEHide()
  4407. {
  4408.       union REGS r;
  4409.  
  4410.       r.w.ax=0x0002;
  4411.       r.w.bx=0x0000;
  4412.       r.w.cx=0x0000;
  4413.       r.w.dx=0x0000;
  4414.       int386(0x33,&r,&r);
  4415. }
  4416.  
  4417. BOOL MOUSEReset()
  4418. {
  4419.       union REGS r;
  4420.  
  4421.       r.w.ax=0x0000;
  4422.       r.w.bx=0x0000;
  4423.       r.w.cx=0x0000;
  4424.       r.w.dx=0x0000;
  4425.       int386(0x33,&r,&r);
  4426.       if(r.w.ax==0) return( FALSE ); else return( TRUE );
  4427. }
  4428.  
  4429. //---------------------------------------------------------------------------
  4430.  
  4431. // get mouse x,y movement and button status - also checks for double clicks
  4432.  
  4433. void MOUSEGet( WORD &Mx, WORD &My, UWORD &Mb )
  4434. {
  4435.       union REGS r;
  4436.  
  4437.       Mb=0;
  4438.       r.w.ax=0x0003;
  4439.       int386(0x33,&r,&r);
  4440.       Mb=r.w.bx;
  4441.  
  4442.       Mx=My=0;
  4443.  
  4444.       r.w.ax=0x000b;
  4445.       int386(0x33,&r,&r);
  4446.       Mx=r.w.cx; My=r.w.dx;
  4447. }
  4448.  
  4449. //---------------------------------------------------------------------------
  4450.  
  4451. void MouseResponse( UWORD *d, BOOL *f )
  4452. {
  4453.     WORD mx, my;
  4454.     UWORD mb;
  4455.  
  4456.     MOUSEGet( mx, my, mb );
  4457.  
  4458.     if( abs(mx) > abs(my) ) {    //Find the most pushed in direction
  4459.         if( mx < -2 ) *d = PLAYERLEFT;
  4460.         if( mx > 2 ) *d = PLAYERRIGHT;
  4461.         }
  4462.     else {
  4463.         if( my < -2 ) *d = PLAYERUP;
  4464.         if( my > 2 ) *d = PLAYERDOWN;
  4465.         }
  4466.  
  4467.     if( (mb & MOUSE_BUTTON_LEFT ) != 0 ) *f = TRUE;
  4468.     else *f=FALSE;
  4469. }
  4470.  
  4471. //---------------------------------------------------------------------------
  4472.  
  4473. void KeyboardResponse( UWORD *d, BOOL *f )
  4474. {
  4475.       if(KEY[Key_Up]) *d=PLAYERUP;
  4476.       if(*d==0) {
  4477.         if(KEY[Key_Down]) *d=PLAYERDOWN;
  4478.         if(*d==0) {
  4479.           if(KEY[Key_Left]) *d=PLAYERLEFT;
  4480.           if(*d==0 && KEY[Key_Right]) *d=PLAYERRIGHT;
  4481.           }
  4482.         }
  4483.     if(KEY[Key_Fire]) *f=TRUE;
  4484.     else *f=FALSE;
  4485. }
  4486.  
  4487. //---------------------------------------------------------------------------
  4488.  
  4489. void PlayerResponse(UWORD *d,BOOL *f)
  4490. {
  4491.     //First do default keyboard
  4492.  
  4493.     *d=0;
  4494.  
  4495.       if(KEY[K_UP]) *d=PLAYERUP;
  4496.       if(*d==0) {
  4497.         if(KEY[K_DOWN]) *d=PLAYERDOWN;
  4498.         if(*d==0) {
  4499.           if(KEY[K_LEFT]) *d=PLAYERLEFT;
  4500.           if(*d==0 && KEY[K_RIGHT]) *d=PLAYERRIGHT;
  4501.           }
  4502.         }
  4503.     if(KEY[K_FIRE]) *f=TRUE;
  4504.     else *f=FALSE;
  4505.  
  4506.     if( *d != 0 || *f != 0 ) return; //Player used default
  4507.  
  4508.     switch( AuxInput ) {
  4509.         case CONTROL_JOYSTICK:
  4510.             JoystickResponse( d, f );
  4511.             break;
  4512.         case CONTROL_MOUSE:
  4513.             MouseResponse( d, f );
  4514.             break;
  4515.         case CONTROL_KEYBOARD:
  4516.             KeyboardResponse( d, f );
  4517.             break;
  4518.         }
  4519. }
  4520.  
  4521. //---------------------------------------------------------------------------
  4522.  
  4523. // Main player movement
  4524.  
  4525. void GControlPlayer()
  4526. {
  4527.     SPRITE *Bm;
  4528.       WORD BeamSpr,Plx,Ply;
  4529.       UWORD cl;
  4530.       BOOL Moved=FALSE,DoBeam;
  4531.       BOOL Ku=FALSE,Kd=FALSE,Kl=FALSE,Kr=FALSE;
  4532.     UWORD Dir;
  4533.     BOOL Fire;
  4534.  
  4535.       SPRITE *pl=&GSprite[0];
  4536.  
  4537.     PlayerResponse(&Dir,&Fire);
  4538.  
  4539.     if(FireEnableStatus==FALSE) Fire=FALSE;
  4540.  
  4541.     switch(GPlayerMode) {
  4542.         case INMIDDLE:
  4543.             Accum=1;
  4544.             BombTwoFired=FALSE;
  4545.             if(Dir==PLAYERUP) {
  4546.               if(GPlayerFacing!=FACEUP && (pl->id!=BOMB1 && pl->id!=BOMB2 && pl->id!=BOMB3)) SPRITEAnim(0,AUP,1);
  4547.               Moved=TRUE;
  4548.               GPlayerFacing=FACEUP;
  4549.               if(pl->xcnt==0 && pl->ycnt==0 && pl->y>160) {
  4550.                     //SoundPlay(4);
  4551.                     pl->ymov=-PlayerSpeed;
  4552.                     pl->ycnt=PlayerMoveBy;
  4553.                     }
  4554.               }
  4555.             if(Dir==PLAYERDOWN) {
  4556.               if(GPlayerFacing!=FACEDOWN && (pl->id!=BOMB1 && pl->id!=BOMB2 && pl->id!=BOMB3)) SPRITEAnim(0,ADOWN,1);
  4557.                GPlayerFacing=FACEDOWN;
  4558.               Moved=TRUE;
  4559.               if(pl->xcnt==0 && pl->ycnt==0 && pl->y<256) {
  4560.                     //SoundPlay(4);
  4561.                     pl->ymov=PlayerSpeed;
  4562.                     pl->ycnt=PlayerMoveBy;
  4563.                     }
  4564.               }
  4565.             if(Dir==PLAYERLEFT) {
  4566.               if(GPlayerFacing!=FACELEFT && (pl->id!=BOMB1 && pl->id!=BOMB2 && pl->id!=BOMB3)) SPRITEAnim(0,ALEFT,1);
  4567.               GPlayerFacing=FACELEFT;
  4568.               Moved=TRUE;
  4569.               if(pl->xcnt==0 && pl->ycnt==0 && pl->x>256) {
  4570.                     //SoundPlay(4);
  4571.                     pl->xmov=-PlayerSpeed;
  4572.                     pl->xcnt=PlayerMoveBy;
  4573.                     }
  4574.               }
  4575.             if(Dir==PLAYERRIGHT) {
  4576.               if(GPlayerFacing!=FACERIGHT && (pl->id!=BOMB1 && pl->id!=BOMB2 && pl->id!=BOMB3)) SPRITEAnim(0,ARIGHT,1);
  4577.               GPlayerFacing=FACERIGHT;
  4578.               Moved=TRUE;
  4579.               if(pl->xcnt==0 && pl->ycnt==0 && pl->x<352) {
  4580.                     //SoundPlay(4);
  4581.                     pl->xmov=PlayerSpeed;
  4582.                     pl->xcnt=PlayerMoveBy;
  4583.                     }
  4584.               }
  4585.             if(Fire==TRUE && FireWait==0) {
  4586.               if(((pl->x & 31)!=0) || ((pl->y & 31)!=0)) return;
  4587.                 SoundPlay(11);
  4588.               GPlayerMode=RUNTO;
  4589.               GStartRunx=pl->x;
  4590.               GStartRuny=pl->y;
  4591.               if(pl->id==BOMB2) {
  4592.                     LastBombKill=BOMB2;
  4593.                     BombTwoFired=TRUE;
  4594.                     }
  4595.  
  4596.               switch(GPlayerFacing) {
  4597.                     case FACEUP:
  4598.                           GPlayerRunLine=(pl->x >> 5)-7;
  4599.                       pl->xmov=0;
  4600.                       pl->ymov=-FIRESTEP;
  4601.                       pl->xcnt=0;
  4602.                           pl->ycnt=40;
  4603.                       SPRITEAnim(0,AUP,1);
  4604.                           break;
  4605.                     case FACEDOWN:
  4606.                           GPlayerRunLine=((pl->x >> 5)-7)+8;
  4607.                       pl->xmov=0;
  4608.                       pl->ymov=FIRESTEP;
  4609.                       pl->xcnt=0;
  4610.                           pl->ycnt=40;
  4611.                       SPRITEAnim(0,ADOWN,1);
  4612.                       break;
  4613.                     case FACELEFT:
  4614.                           GPlayerRunLine=((pl->y >> 5)-4)+12;
  4615.                       pl->xmov=-FIRESTEP;
  4616.                       pl->ymov=0;
  4617.                       pl->xcnt=40;
  4618.                           pl->ycnt=0;
  4619.                       SPRITEAnim(0,ALEFT,1);
  4620.                           break;
  4621.                     case FACERIGHT:
  4622.                           GPlayerRunLine=((pl->y >> 5)-4)+4;
  4623.                       pl->xmov=FIRESTEP;
  4624.                       pl->ymov=0;
  4625.                       pl->xcnt=40;
  4626.                           pl->ycnt=0;
  4627.                       SPRITEAnim(0,ARIGHT,1);
  4628.                       break;
  4629.                     }
  4630.                     Moved=TRUE;
  4631.                     FireWait=8;
  4632.               }
  4633.             else if(FireWait>0) FireWait--;
  4634.  
  4635.             if(!Moved) {
  4636.               switch(GPlayerFacing) {
  4637.                     case FACEUP:
  4638.                           SPRITEAnim(0,AUP,1);
  4639.                           break;
  4640.                     case FACEDOWN:
  4641.                           SPRITEAnim(0,ADOWN,1);
  4642.                           break;
  4643.                     case FACELEFT:
  4644.                           SPRITEAnim(0,ALEFT,1);
  4645.                           break;
  4646.                     case FACERIGHT:
  4647.                           SPRITEAnim(0,ARIGHT,1);
  4648.                           break;
  4649.                     }
  4650.               }
  4651.             break;
  4652.  
  4653.         case RUNTO:
  4654.             cl=GPlayerCollision();
  4655.  
  4656.             if(cl!=0 || pl->x==0 ||pl->y==416 ||pl->x==608 ||pl->y==0) {
  4657.               pl->xmov=0;
  4658.               pl->ymov=0;
  4659.               pl->xcnt=0;
  4660.               pl->ycnt=0;
  4661.               if(BombTwoFired==TRUE) {
  4662.                     pl->id=LastBombKill;
  4663.                     if(pl->id<=COLOR4) pl->id+=PCOLOR1;
  4664.                   }
  4665.  
  4666.               Accum=1;
  4667.               GPlayerMode=RUNFROM;
  4668.               switch(GPlayerFacing) {
  4669.                     case FACEUP:
  4670.                           GPlayerFacing=FACEDOWN;
  4671.                       SPRITEAnim(0,ADOWN,1);
  4672.                           break;
  4673.                     case FACEDOWN:
  4674.                           GPlayerFacing=FACEUP;
  4675.                       SPRITEAnim(0,AUP,1);
  4676.                           break;
  4677.                     case FACELEFT:
  4678.                           GPlayerFacing=FACERIGHT;
  4679.                       SPRITEAnim(0,ARIGHT,1);
  4680.                           break;
  4681.                     case FACERIGHT:
  4682.                           GPlayerFacing=FACELEFT;
  4683.                       SPRITEAnim(0,ALEFT,1);
  4684.                           break;
  4685.                     }
  4686.               }
  4687.             break;
  4688.  
  4689.         case RUNFROM:
  4690.             Accum=1; LastKill=-1;
  4691.             Bomb2Sound=FALSE;
  4692.             switch(GPlayerFacing) {
  4693.               case FACEDOWN:
  4694.                     pl->xmov=0;
  4695.                     pl->ymov=FIRESTEP;
  4696.                     pl->xcnt=0;
  4697.                     pl->ycnt=40;
  4698.                     break;
  4699.               case FACEUP:
  4700.                     pl->xmov=0;
  4701.                     pl->ymov=-FIRESTEP;
  4702.                     pl->xcnt=0;
  4703.                     pl->ycnt=40;
  4704.                     break;
  4705.               case FACERIGHT:
  4706.                     pl->xmov=FIRESTEP;
  4707.                     pl->ymov=0;
  4708.                     pl->xcnt=40;
  4709.                     pl->ycnt=0;
  4710.                      break;
  4711.               case FACELEFT:
  4712.                     pl->xmov=-FIRESTEP;
  4713.                     pl->ymov=0;
  4714.                     pl->xcnt=40;
  4715.                     pl->ycnt=0;
  4716.                     break;
  4717.               }
  4718.             if(GPlayerFacing==FACELEFT && pl->x >= GStartRunx) {
  4719.               if(pl->x-16 < GStartRunx) {
  4720.                     pl->xmov=0;
  4721.                     pl->ymov=0;
  4722.                     pl->xcnt=0;
  4723.                     pl->ycnt=0;
  4724.                     pl->x=GStartRunx;
  4725.                     GPlayerMode=INMIDDLE;
  4726.                     GPlayerRunLine=-1;
  4727.                     }
  4728.               }
  4729.             if(GPlayerFacing==FACERIGHT && pl->x <= GStartRunx) {
  4730.               if(pl->x+16 > GStartRunx) {
  4731.                     pl->xmov=0;
  4732.                     pl->ymov=0;
  4733.                     pl->xcnt=0;
  4734.                     pl->ycnt=0;
  4735.                     pl->x=GStartRunx;
  4736.                     GPlayerMode=INMIDDLE;
  4737.                     GPlayerRunLine=-1;
  4738.                     }
  4739.               }
  4740.             if(GPlayerFacing==FACEUP && pl->y >= GStartRuny) {
  4741.               if(pl->y-16 < GStartRuny) {
  4742.                     pl->xmov=0;
  4743.                     pl->ymov=0;
  4744.                     pl->xcnt=0;
  4745.                     pl->ycnt=0;
  4746.                     pl->y=GStartRuny;
  4747.                     GPlayerMode=INMIDDLE;
  4748.                     GPlayerRunLine=-1;
  4749.                     }
  4750.               }
  4751.             if(GPlayerFacing==FACEDOWN && pl->y <= GStartRuny) {
  4752.               if(pl->y+16 > GStartRuny) {
  4753.                     pl->xmov=0;
  4754.                     pl->ymov=0;
  4755.                     pl->xcnt=0;
  4756.                     pl->ycnt=0;
  4757.                     pl->y=GStartRuny;
  4758.                     GPlayerMode=INMIDDLE;
  4759.                     GPlayerRunLine=-1;
  4760.                     }
  4761.               }
  4762.             break;
  4763.         }
  4764.  
  4765.     //Light Beam
  4766.  
  4767.     if(((GSprite[0].x & 31)==0) && ((GSprite[0].y & 31)==0) && GPlayerMode!=INMIDDLE) {
  4768.         if(DetailLevel==0) {
  4769.             BeamSpr=SPRITEGetFree();
  4770.             Bm=&GSprite[BeamSpr];
  4771.             Bm->id=LIGHTBEAM;
  4772.             Bm->line=-1;
  4773.             Bm->walk=FALSE;
  4774.             Bm->fly=FALSE;
  4775.             Bm->oldx=0;
  4776.             Bm->oldy=0;
  4777.             Bm->xmov=0;
  4778.             Bm->ymov=0;
  4779.             Bm->clag=65000;
  4780.             Bm->x=GSprite[0].x;
  4781.             Bm->y=GSprite[0].y;
  4782.             Bm->active=TRUE;
  4783.  
  4784.             UWORD PID=pl->id;
  4785.             UWORD beam;
  4786.             if(PID>=PCOLOR1 && PID<=PCOLOR4) PID-=PCOLOR1;
  4787.             if(GSprite[0].id>=BOMB1 && GSprite[0].id<=BOMB3) beam=4*4;
  4788.             else beam=4*PID;
  4789.             switch(GPlayerFacing) {
  4790.               case FACEUP:
  4791.                     SPRITENewAnim(BeamSpr,beam+2,2);
  4792.                     break;
  4793.               case FACEDOWN:
  4794.                     SPRITENewAnim(BeamSpr,beam+3,2);
  4795.                     break;
  4796.               case FACELEFT:
  4797.                     SPRITENewAnim(BeamSpr,beam+1,2);
  4798.                     break;
  4799.               case FACERIGHT:
  4800.                     SPRITENewAnim(BeamSpr,beam,2);
  4801.                     break;
  4802.               }
  4803.             }
  4804.         }
  4805. }
  4806.  
  4807. //---------------------------------------------------------------------------
  4808.  
  4809. void WinPlayer()
  4810. {
  4811.       UWORD i;
  4812.       UWORD exc,exx,cl;
  4813.       WORD bx,by;
  4814.     UDWORD Turn;
  4815.     SPRITE *s;
  4816.  
  4817.     s=&GSprite[0];
  4818.  
  4819.     FireEnableStatus=FALSE;
  4820.  
  4821.       for(i=0;i<80;i++) {
  4822.        FindLineCount();
  4823.        MonitorWalking();
  4824.         if(GPlayerMode!=INMIDDLE) {
  4825.           GControlPlayer();
  4826.           }
  4827.         else {
  4828.           break;
  4829.           }
  4830.         PANELUpdate();
  4831.         GRAPHICUpdate();
  4832.         }
  4833. }
  4834.  
  4835. // Player explosion
  4836.  
  4837. void KillPlayer()
  4838. {
  4839.       UWORD i;
  4840.       UWORD exc,exx,cl;
  4841.       WORD bx,by;
  4842.     UDWORD Turn;
  4843.     SPRITE *s;
  4844.  
  4845.     s=&GSprite[0];
  4846.  
  4847.     FireEnableStatus=FALSE;
  4848.  
  4849.       for(i=0;i<80;i++) {
  4850.        FindLineCount();
  4851.        MonitorWalking();
  4852.         if(GPlayerMode!=INMIDDLE) {
  4853.           GControlPlayer();
  4854.           }
  4855.         else {
  4856.           break;
  4857.           }
  4858.         PANELUpdate();
  4859.         GRAPHICUpdate();
  4860.         }
  4861.  
  4862.    s->animtog=FALSE;
  4863.  
  4864.     s->fly=TRUE;
  4865.       s->dline=SPRLINE;
  4866.       s->sline=1;
  4867.       s->pline=5;
  4868.       s->clag=65000;
  4869.       s->update=TRUE;
  4870.       WorkoutLine(s,s->x,s->y,304,208);
  4871.  
  4872.     while(s->dline!=NOLINE) {
  4873.         PANELUpdate();
  4874.         GRAPHICUpdate();
  4875.         }
  4876.  
  4877.     SoundPlay(10);
  4878.  
  4879.     Turn=GSprite[0].anim << 16;
  4880.  
  4881.     for(exc=0;exc<14;exc++) {
  4882.         if(exc<13) {
  4883.             cl=SPRITEGetFree();
  4884.             GSprite[cl].active=TRUE;
  4885.             GSprite[cl].id=EXPLODE;
  4886.             GSprite[cl].walk=FALSE;
  4887.             GSprite[cl].fly=TRUE;
  4888.             GSprite[cl].line=-1;
  4889.             GSprite[cl].xmov=0;
  4890.             GSprite[cl].ymov=0;
  4891.             GSprite[cl].oldx=0;
  4892.             GSprite[cl].oldy=0;
  4893.             GSprite[cl].dline=NOLINE;
  4894.             GSprite[cl].clag=65000;
  4895.  
  4896.             bx=rand() & 31;
  4897.             by=rand() & 31;
  4898.  
  4899.             GSprite[cl].x=(GSprite[0].x-16)+bx;
  4900.             GSprite[cl].y=(GSprite[0].y-16)+by;
  4901.  
  4902.             SPRITENewAnim(cl,1,0);
  4903.             GSprite[cl].animtime=3;
  4904.             }
  4905.  
  4906.         for(exx=0;exx<8;exx++) {
  4907.             if((NEWspr!=-1) || (WalkLine!=-1)) {
  4908.                NewEnemy();
  4909.                EnemyAppear();
  4910.                MonitorWalking();
  4911.                 }
  4912.             Turn+=16384;
  4913.             if((Turn>>16) > 4) Turn=0;
  4914.             SPRITENewAnim(0,Turn>>16,0);    //spin player sprite
  4915.  
  4916.               PANELUpdate();
  4917.           GRAPHICUpdate();
  4918.             }
  4919.         SoundPlay(10);
  4920.  
  4921.         if(exc==13) {
  4922.             //304 208
  4923.             SetStar(272,208,272-32,208);    //left side
  4924.             SetStar(336,208,336+32,208);    //right side
  4925.  
  4926.             SetStar(272+8,176+8,(272-32)+12,(176-32)+12); //top left
  4927.             SetStar(272+8,240-8,(272-32)+12,(240+32)-12); //bottom left
  4928.  
  4929.             SetStar(304,176,304,176-32);    //top mid
  4930.             SetStar(304,240,304,240+32);    //bottom mid
  4931.  
  4932.             SetStar(336-8,176+8,(336+32)-12,(176-32)+12); //top right
  4933.             SetStar(336-8,240-8,(336+32)-12,(240+32)-12); //bottom right
  4934.             }
  4935.         }
  4936.  
  4937.       for(exx=0;exx<4;exx++) {
  4938.         PANELUpdate();
  4939.         GRAPHICUpdate();
  4940.         }
  4941.  
  4942.     GSprite[0].id=EXPLODE;
  4943.       SPRITENewAnim(0,1,0);
  4944.  
  4945.       for(exx=0;exx<8;exx++) {
  4946.         PANELUpdate();
  4947.         GRAPHICUpdate();
  4948.         }
  4949.     SoundPlay(10);
  4950.  
  4951.       for(exx=0;exx<64;exx++) {
  4952.         PANELUpdate();
  4953.         GRAPHICUpdate();
  4954.         }
  4955.  
  4956.     // Switch off all animations
  4957.     for( i=0; i < NUMSPRITES; i++) GSprite[i].animtog = FALSE;
  4958.  
  4959.     for(exx=0;exx<4;exx++) {
  4960.         PANELUpdate();
  4961.         GRAPHICUpdate();
  4962.         }
  4963.     FireEnableStatus=TRUE;
  4964. }
  4965.  
  4966. //===========================================================================
  4967. // Score functions
  4968. //===========================================================================
  4969.  
  4970. // Fill string with leading zeros
  4971.  
  4972. void PadLeadingZeros(BYTE *s,UWORD l)
  4973. {
  4974.     UWORD pos,len;
  4975.     BYTE tmpa[32],tmpb[32];
  4976.     BYTE *p;
  4977.  
  4978.     strcpy(tmpa,"0000000000");
  4979.     strcat(tmpa,s);
  4980.  
  4981.     len=strlen(tmpa);
  4982.     pos=len-l;
  4983.  
  4984.     p=&tmpb[0];
  4985.     while(pos!=len) {
  4986.         *(p++)=tmpa[pos];
  4987.         pos++;
  4988.        }
  4989.     tmpb[pos]=0;
  4990.     strcpy(s,tmpb);
  4991. }
  4992.  
  4993. //---------------------------------------------------------------------------
  4994.  
  4995. // Maintain the rolling score digits
  4996.  
  4997. void ScoreTrack()
  4998. {
  4999.       WORD i;
  5000.  
  5001.       for(i=0;i<7;i++) {
  5002.         if(GSprite[Score[i]].animtog==TRUE) return;
  5003.         }
  5004.  
  5005.       BOOL spin=FALSE;
  5006.       for(i=0;i<7;i++) {
  5007.         if(GSprite[Score[i]].anim==1) {
  5008.           GSprite[Score[i]].id=DIGIT0+Digit[i];
  5009.           SPRITENewAnim(Score[i],2,0);
  5010.           spin=TRUE;
  5011.           }
  5012.         }
  5013.       if(spin==TRUE) return;
  5014.  
  5015.       if(GBScore==0 || GPlayerMode==RUNTO) return;
  5016.  
  5017.       GScore+=GBScore;
  5018.       GBScore=0;
  5019.  
  5020.       BYTE tmp[20];
  5021.       itoa(GScore,tmp,10);
  5022.       i=7-strlen(tmp);
  5023.  
  5024.       UWORD dp=0,aw=1;
  5025.       BOOL RollOn=FALSE;
  5026.  
  5027.       while(i<7) {
  5028.         Digit[i]=tmp[dp++]-48;
  5029.         if(Digit[i]!=ODigit[i] || RollOn==TRUE) {
  5030.           GSprite[Score[i]].id=DIGIT0+ODigit[i];
  5031.           SPRITENewAnim(Score[i],1,0);
  5032.           ODigit[i]=Digit[i];
  5033.           RollOn=TRUE;
  5034.           }
  5035.         i++;
  5036.         }
  5037.       SPRITENewAnim(Score[5],1,0);
  5038.       SPRITENewAnim(Score[6],1,0);
  5039. }
  5040.  
  5041. //---------------------------------------------------------------------------
  5042.  
  5043. // Maintain the number of kills digits
  5044.  
  5045. void KillsTrack()
  5046. {
  5047.       WORD i;
  5048.  
  5049.       for(i=0;i<4;i++) {
  5050.         if(GSprite[SKill[i]].animtog==TRUE) return;
  5051.         }
  5052.  
  5053.       BOOL spin=FALSE;
  5054.       for(i=0;i<4;i++) {
  5055.         if(GSprite[SKill[i]].anim==1) {
  5056.           GSprite[SKill[i]].id=DIGIT0+KDigit[i];
  5057.           SPRITENewAnim(SKill[i],2,0);
  5058.           spin=TRUE;
  5059.           }
  5060.         }
  5061.       if(spin==TRUE) return;
  5062.  
  5063.       if(GBKills==0 || GPlayerMode==RUNTO) return;
  5064.  
  5065.       GBKills=0;
  5066.  
  5067.       BYTE tmp[20];
  5068.     if(Kills<0) Kills=0;
  5069.       itoa(Kills,tmp,10); //Kills counting down
  5070.  
  5071.     PadLeadingZeros(tmp,4);
  5072.     i=0;
  5073.  
  5074.       UWORD dp=0;
  5075.       BOOL RollOn=FALSE;
  5076.  
  5077.     while(i<4) {
  5078.         KDigit[i]=tmp[dp++]-48;
  5079.         if((KDigit[i]!=KODigit[i]) || RollOn==TRUE) {
  5080.           GSprite[SKill[i]].id=DIGIT0+KODigit[i];
  5081.           SPRITENewAnim(SKill[i],1,0);
  5082.           KODigit[i]=KDigit[i];
  5083.             RollOn=TRUE;
  5084.           }
  5085.         i++;
  5086.         }
  5087. }
  5088.  
  5089. //---------------------------------------------------------------------------
  5090.  
  5091. // Maintain the level number digits
  5092.  
  5093. void LevelsTrack()
  5094. {
  5095.       WORD i;
  5096.  
  5097.       for(i=0;i<2;i++) {
  5098.         if(GSprite[SLevel[i]].animtog==TRUE) return;
  5099.         }
  5100.  
  5101.       BOOL spin=FALSE;
  5102.       for(i=0;i<2;i++) {
  5103.         if(GSprite[SLevel[i]].anim==1) {
  5104.           GSprite[SLevel[i]].id=DIGIT0+LDigit[i];
  5105.           SPRITENewAnim(SLevel[i],2,0);
  5106.           spin=TRUE;
  5107.           }
  5108.         }
  5109.       if(spin==TRUE) return;
  5110.  
  5111.       if(Level==OldLevel) return;
  5112.       OldLevel=Level;
  5113.  
  5114.       BYTE tmp[20];
  5115.       itoa(Level,tmp,10);
  5116.       i=2-strlen(tmp);
  5117.  
  5118.       UWORD dp=0;
  5119.  
  5120.       while(i<2) {
  5121.         LDigit[i]=tmp[dp++]-48;
  5122.         if(LDigit[i]!=LODigit[i]) {
  5123.           GSprite[SLevel[i]].id=DIGIT0+LODigit[i];
  5124.           SPRITENewAnim(SLevel[i],1,0);
  5125.           LODigit[i]=LDigit[i];
  5126.           }
  5127.         i++;
  5128.         }
  5129. }
  5130.  
  5131. //---------------------------------------------------------------------------
  5132.  
  5133. // Setup the score digit sprites
  5134.  
  5135. void ScoreSetup()
  5136. {
  5137.       UWORD fs;
  5138.     BYTE tmp[20];
  5139.  
  5140.     for(UWORD i=0;i<7;i++) {
  5141.         fs=SPRITEGetFree();
  5142.         Digit[i]=0;
  5143.         ODigit[i]=0;
  5144.         Score[i]=fs;
  5145.         GSprite[fs].active=TRUE;
  5146.         GSprite[fs].y=32;
  5147.         GSprite[fs].x=i*32;
  5148.         GSprite[fs].id=DIGIT0;
  5149.         GSprite[fs].walk=FALSE;
  5150.         GSprite[fs].fly=FALSE;
  5151.         GSprite[fs].spawnid=-1;
  5152.         SPRITENewAnim(fs,0,0);
  5153.         }
  5154.  
  5155.       itoa(Kills,tmp,10);
  5156.     PadLeadingZeros(tmp,4);
  5157.  
  5158.     for(i=0;i<4;i++) {
  5159.         fs=SPRITEGetFree();
  5160.         KDigit[i]=tmp[i]-48;
  5161.         KODigit[i]=tmp[i]-48;
  5162.         SKill[i]=fs;
  5163.         GSprite[fs].active=TRUE;
  5164.         GSprite[fs].y=32;
  5165.         GSprite[fs].x=(32*16)+(i*32);
  5166.         GSprite[fs].id=DIGIT0+tmp[i]-48;
  5167.         GSprite[fs].walk=FALSE;
  5168.         GSprite[fs].fly=FALSE;
  5169.         GSprite[fs].spawnid=-1;
  5170.         SPRITENewAnim(fs,0,0);
  5171.         }
  5172.  
  5173.     for(i=0;i<2;i++) {
  5174.         fs=SPRITEGetFree();
  5175.         LDigit[i]=0;
  5176.         LODigit[i]=0;
  5177.         SLevel[i]=fs;
  5178.         GSprite[fs].active=TRUE;
  5179.         GSprite[fs].y=416-32;
  5180.         GSprite[fs].x=(32*16)+(2*32)+(i*32);
  5181.         GSprite[fs].id=DIGIT0+i;
  5182.         GSprite[fs].walk=FALSE;
  5183.         GSprite[fs].fly=0;
  5184.         GSprite[fs].spawnid=-1;
  5185.         SPRITENewAnim(fs,0,0);
  5186.         }
  5187.       LODigit[1]=1;
  5188. }
  5189.  
  5190. //---------------------------------------------------------------------------
  5191.  
  5192. void NetSpriteSetup()
  5193. {
  5194.     DWORD i, p;
  5195.       UWORD fs;
  5196.  
  5197.     p = 0;
  5198.  
  5199.     for(i=0;i<20;i++) {
  5200.         fs = SPRITEGetFree();
  5201.         NET_Name_Sprite[ i ] = fs;
  5202.         GSprite[fs].active=TRUE;
  5203.         GSprite[fs].y=448;
  5204.         GSprite[fs].x=48 + p;
  5205.         NET_Name_Posx[ i ] = 48 + p;
  5206.         GSprite[fs].id=NETFONT;
  5207.         GSprite[fs].walk=FALSE;
  5208.         GSprite[fs].fly=FALSE;
  5209.         GSprite[fs].spawnid=-1;
  5210.         SPRITENewAnim(fs,47,0);
  5211.         NET_Name_Letter[ i ] = ' ';
  5212.         if( ( (i+1) % 5 ) == 0 ) p += 64;
  5213.         p += 16;
  5214.         }
  5215. }
  5216.  
  5217. //===========================================================================
  5218. // Setup for player
  5219. //===========================================================================
  5220.  
  5221. void PlayerSetup()
  5222. {
  5223.       GSprite[0].active=TRUE;
  5224.       GSprite[0].x=MAPUpdate[(10*MAPWIDTH)+20].x;
  5225.       GSprite[0].y=MAPUpdate[(10*MAPWIDTH)+20].y;
  5226.       GSprite[0].id=PCOLOR1+(rand() & 3);
  5227.       GSprite[0].walk=FALSE;
  5228.       GSprite[0].fly=FALSE;
  5229.       GSprite[0].spawnid=-1;
  5230.       GPlayerMode=INMIDDLE;
  5231.       GPlayerRunLine=-1;
  5232.       SPRITENewAnim(0,2,1);
  5233. }
  5234.  
  5235. //===========================================================================
  5236. // Set real state variables for level
  5237. //===========================================================================
  5238.  
  5239. void SetLevel(UWORD newlevel)
  5240. {
  5241.     UWORD lev = newlevel;
  5242.     BYTE tmp[32];
  5243.  
  5244.     lev--;
  5245.  
  5246.     if( lev > 9 ) lev = 9;
  5247.  
  5248.     NET_Player_Level = lev;
  5249.  
  5250.       TimeSpeed=LevelSet[lev].Speed;
  5251.       LevelBombs=LevelSet[lev].Bombs;
  5252.  
  5253.     Kills=LevelSet[lev].Kills;
  5254.  
  5255.       GColorThreshold=LevelSet[lev].ColorThreshold;
  5256.       WhichBombs=LevelSet[lev].WhichBombs;
  5257.       BonusRand=LevelSet[lev].BonusRand;
  5258.  
  5259.       if( newlevel < MAXLEVELS+1 ) {
  5260.         strcpy( tmp, "gfx\\" );
  5261.         strcat( tmp, LevelSet[lev].BackImage );
  5262.         BackPcx.Load( tmp, buf3 );
  5263.         }
  5264.  
  5265.     EnemyLeadIn=DifficultySet[Difficulty-1];
  5266.  
  5267.     StrobeColor1=LevelSet[lev].StrobeColor1;
  5268.     StrobeColor2=LevelSet[lev].StrobeColor2;
  5269.     StrobeR1=BackPcx.palette[StrobeColor1*3];
  5270.     StrobeG1=BackPcx.palette[(StrobeColor1*3)+1];
  5271.     StrobeB1=BackPcx.palette[(StrobeColor1*3)+2];
  5272.     StrobeR2=BackPcx.palette[StrobeColor2*3];
  5273.     StrobeG2=BackPcx.palette[(StrobeColor2*3)+1];
  5274.     StrobeB2=BackPcx.palette[(StrobeColor2*3)+2];
  5275.  
  5276.     switch(lev) {
  5277.         case 0:
  5278.             MusicPlay(29);
  5279.             break;
  5280.         case 1:
  5281.             MusicPlay(30);
  5282.             break;
  5283.         case 2:
  5284.             MusicPlay(31);
  5285.             break;
  5286.         case 3:
  5287.             MusicPlay(32);
  5288.             break;
  5289.         case 4:
  5290.             MusicPlay(33);
  5291.             break;
  5292.         case 5:
  5293.             MusicPlay(34);
  5294.             break;
  5295.         case 6:
  5296.             MusicPlay(29);
  5297.             break;
  5298.         case 7:
  5299.             MusicPlay(30);
  5300.             break;
  5301.         default:
  5302.             MusicPlay(29);
  5303.             break;
  5304.         }
  5305. }
  5306.  
  5307. //===========================================================================
  5308. // Create preset number of enemies
  5309. //===========================================================================
  5310.  
  5311. void CreateEnemyLeadIn()
  5312. {
  5313.     UWORD i;
  5314.  
  5315.     if(EnemyLeadIn == 0) return;
  5316.  
  5317.     DoingLeadIn=TRUE;
  5318.     for(i=0;i<EnemyLeadIn;i++) {
  5319.       FindLineCount();
  5320.         NEWspr=-1;
  5321.         CreateEnemy();
  5322.         AppearCount=0;
  5323.       NewInstantEnemy();
  5324.         EnemyAppear();
  5325.         GRAPHICUpdateNotVisible();
  5326.         }
  5327.  
  5328.     GMorphPal(128,192,8,(UBYTE *) WPalette);  //Strobe while flash
  5329.       GMorphPal(0,255,8,(UBYTE *) BackPcx.palette);
  5330.  
  5331.     GRAPHICUpdate();
  5332.     DoingLeadIn=FALSE;
  5333. }
  5334.  
  5335. //===========================================================================
  5336. // Next level functions
  5337. //===========================================================================
  5338.  
  5339. void VertCopy(WORD x,WORD y,WORD w,WORD h,WORD bottom)
  5340. {
  5341.    TUPDATE *m1,*m2;
  5342.     UDWORD pos1,pos2,i;
  5343.     UDWORD tstart,tend,bstart,bend;
  5344.  
  5345.     if(y<0) y=0;
  5346.     if(h>bottom) h=bottom;
  5347.     //if(h>479) h=479;
  5348.     if(x<0) x=0;
  5349.     if(w>639) w=639;
  5350.  
  5351.     // Copy the bitmap
  5352.  
  5353.     pos1=Yoffset[y] + x;
  5354.     pos2=Yoffset[y] + x+w;
  5355.     for(i=0;i<h+1;i++) {
  5356.         *(buf1+pos1)=*(buf2+pos1);
  5357.         *(buf1+pos2)=*(buf2+pos2);
  5358.         pos1+=640; pos2+=640;
  5359.         }
  5360.  
  5361.     // Now update map positions
  5362.  
  5363.     tstart=y>>4;
  5364.     tend=(y+h)>>4;
  5365.     bstart=Moffset[y>>4]+((x+w)>>4);
  5366.    bend=Moffset[(y+h)>>4]+((x+w)>>4);
  5367.    m1=&MAPUpdate[Moffset[tstart]+(x>>4)];
  5368.    m2=&MAPUpdate[bstart];
  5369.     for(i=tstart;i<=tend;i++) {
  5370.         m1->phase=1;
  5371.         m2->phase=1;
  5372.         m1+=MAPWIDTH;
  5373.         m2+=MAPWIDTH;
  5374.         }
  5375. }
  5376.  
  5377. //---------------------------------------------------------------------------
  5378.  
  5379. inline void MarkCopy(WORD x,WORD y)
  5380. {
  5381.     UDWORD pos1;
  5382.     UDWORD tstart;
  5383.  
  5384.     if(y<0) y=0;
  5385.     //if(y>447) y=447;
  5386.     if(y>479) y=479;
  5387.     if(x<0) x=0;
  5388.     if(x>639) x=639;
  5389.  
  5390.     // Copy the bitmap
  5391.  
  5392.     pos1=Yoffset[y] + x;
  5393.     *(buf1+pos1)=*(buf2+pos1);
  5394.  
  5395.     // Now update map positions
  5396.  
  5397.     tstart=Moffset[y>>4]+(x>>4);
  5398.    MAPUpdate[tstart].phase=1;
  5399. }
  5400.  
  5401. //---------------------------------------------------------------------------
  5402.  
  5403. void HorzCopy(WORD x,WORD y,WORD w,WORD h)
  5404. {
  5405.    TUPDATE *m1,*m2;
  5406.     UDWORD pos1,pos2,i;
  5407.     UDWORD tstart,tend,bstart,bend;
  5408.  
  5409.     if(x<0) x=0;
  5410.     if(w>639) w=639;
  5411.     if(y<0) y=0;
  5412.     //if(h>447) h=447;
  5413.     if(h>479) h=479;
  5414.  
  5415.     // Copy the bitmap rectangle
  5416.  
  5417.     pos1=Yoffset[y] + x;
  5418.     memcpy(buf1+pos1,buf2+pos1,w);
  5419.     pos1=Yoffset[y+h] + x;
  5420.     memcpy(buf1+pos1,buf2+pos1,w);
  5421.  
  5422.     // Now update map positions
  5423.  
  5424.     tstart=Moffset[y>>4]+(x>>4);
  5425.     tend=Moffset[y>>4]+((x+w)>>4);
  5426.     bstart=Moffset[(y+h)>>4]+(x>>4);
  5427.    bend=Moffset[(y+h)>>4]+((x+w)>>4);
  5428.    m1=&MAPUpdate[tstart];
  5429.    m2=&MAPUpdate[bstart];
  5430.     for(i=tstart;i<=tend;i++) {
  5431.         m1->phase=1;
  5432.         m2->phase=1;
  5433.         m1++;
  5434.         m2++;
  5435.         }
  5436. }
  5437.  
  5438. //---------------------------------------------------------------------------
  5439.  
  5440. void THorzCopy(WORD x,WORD y,WORD w)
  5441. {
  5442.    TUPDATE *m1;
  5443.     UDWORD pos1,i;
  5444.     UDWORD tstart,tend;
  5445.  
  5446.     if(x<0) x=0;
  5447.     if(x>639) x=639;
  5448.     if(w+x>639) w=640-x;
  5449.     //if(y>447) y=447;
  5450.     if(y>479) y=479;
  5451.     if(y<0) y=0;
  5452.  
  5453.     // Copy the bitmap rectangle
  5454.  
  5455.     pos1=Yoffset[y] + x;
  5456.     memcpy(buf1+pos1,buf2+pos1,w);
  5457.  
  5458.     // Now update map positions
  5459.  
  5460.     tstart=Moffset[y>>4]+(x>>4);
  5461.     tend=Moffset[y>>4]+((x+w)>>4);
  5462.  
  5463.     m1=&MAPUpdate[tstart];
  5464.  
  5465.     i=tstart;
  5466.     while( (i<=tend) && (i<MAPSIZE)) {
  5467.         m1->phase=1;
  5468.         m1++;
  5469.         i++;
  5470.         }
  5471. }
  5472.  
  5473. //---------------------------------------------------------------------------
  5474.  
  5475. void RectGrow()
  5476. {
  5477.     UDWORD i,j,k;
  5478.    DWORD x,y;
  5479.     DWORD w,h;
  5480.     DWORD v;
  5481.  
  5482.     memcpy(buf2,buf3,307200);
  5483.     GSprite[0].forcedupdate=TRUE;
  5484.     SPRITEPrepare();
  5485.     SPRITEUpdateBuffer2();
  5486.  
  5487.     v=1<<16;
  5488.     x=319-64; y=223-64;
  5489.     w=129; h=129;
  5490.  
  5491.     while(x>0) {
  5492.         WaitTimer();
  5493.         NET_Update();
  5494.         MAPRefresh();
  5495.  
  5496.         for(i=0;i<(v>>16);i++) {
  5497.             if(y>0) {
  5498.                 for(j=0;j<3;j++) {
  5499.                     HorzCopy(x-j,y-j,w+(j*2),h+(j*2));
  5500.                     }
  5501.                   }
  5502.             if(x>0) {
  5503.                 for(j=0;j<4;j++) {
  5504.                     VertCopy(x-j,y-j,w+(j*2),h+(j*2),447);
  5505.                     }
  5506.                 }
  5507.             x-=4; w+=8;
  5508.             y-=3; h+=6;
  5509.  
  5510.             if(x<0 && y<0) break;
  5511.             }
  5512.         v+=4096;
  5513.         BACKMapRefresh();
  5514.         }
  5515.  
  5516.     MAPRefresh();
  5517.  
  5518.     for( i=0; i<33; i++ ) {
  5519.         HorzCopy(0,0,640,447+i);
  5520.         }
  5521.  
  5522.     BACKMapRefresh();
  5523.  
  5524.     v=1<<16;
  5525.     x=319; y=223;
  5526.     w=1; h=1;
  5527.  
  5528.     while(x>319-64) {
  5529.         WaitTimer();
  5530.         MAPRefresh();
  5531.  
  5532.         for(i=0;i<(v>>16);i++) {
  5533.             if(y>0) {
  5534.                 for(j=0;j<4;j++) {
  5535.                     HorzCopy(x-j,y-j,w+(j*2),h+(j*2));
  5536.                     }
  5537.                 }
  5538.             if(x>0) {
  5539.                 for(j=0;j<4;j++) {
  5540.                     VertCopy(x-j,y-j,w+(j*2),h+(j*2),446);
  5541.                     }
  5542.                 }
  5543.             x-=4; w+=8;
  5544.             y-=4; h+=8;
  5545.  
  5546.             if(x<0) break;
  5547.             }
  5548.         v+=4096;
  5549.         BACKMapRefresh();
  5550.         }
  5551.     BACKMapRefresh();
  5552.     MAPRefresh();
  5553.  
  5554.     memcpy(buf2,buf3,307200);
  5555.  
  5556.     GRAPHICUpdate();
  5557.    GRAPHICUpdate();
  5558. }
  5559.  
  5560. //---------------------------------------------------------------------------
  5561.  
  5562. void RectGrowFullScreen()
  5563. {
  5564.     UDWORD i,j,k;
  5565.    DWORD x,y;
  5566.     DWORD w,h;
  5567.     DWORD v;
  5568.  
  5569.     memcpy(buf2,buf3,307200);
  5570.  
  5571.     v=1<<16;
  5572.     x=319; y=239;
  5573.     w=1; h=1;
  5574.  
  5575.     while(x>0) {
  5576.         WaitTimer();
  5577.         NET_Update();
  5578.         MAPRefresh();
  5579.  
  5580.         for(i=0;i<(v>>16);i++) {
  5581.             if(y>0) {
  5582.                 for(j=0;j<4;j++) {
  5583.                     HorzCopy(x-j,y-j,w+(j*2),h+(j*2));
  5584.                     }
  5585.                 }
  5586.             if(x>0) {
  5587.                 for(j=0;j<4;j++) {
  5588.                     VertCopy(x-j,y-j,w+(j*2),h+(j*2),479);
  5589.                     }
  5590.                 }
  5591.             x-=4; w+=8;
  5592.             y-=4; h+=8;
  5593.  
  5594.             if(x<0) break;
  5595.             }
  5596.         v+=4096;
  5597.         BACKMapRefresh();
  5598.         }
  5599.     BACKMapRefresh();
  5600.     MAPRefresh();
  5601.  
  5602.     memcpy(buf2,buf3,307200);
  5603.  
  5604.     GRAPHICUpdate();
  5605.    GRAPHICUpdate();
  5606. }
  5607.  
  5608. //---------------------------------------------------------------------------
  5609.  
  5610. void ShuffleOff()
  5611. {
  5612.     DWORD i,j,k;
  5613.     DWORD LineCount,CurrLine;
  5614.     WORD Spr,mx,my,cx,cy,Cline;
  5615.     BOOL DoneSound;
  5616.     SPRITE *s;
  5617.  
  5618.     for(CurrLine=0;CurrLine<16;CurrLine++) {
  5619.         DoneSound=FALSE;
  5620.  
  5621.         Cline=CurrLine;
  5622.  
  5623.         if(Cline<4) {
  5624.             mx=0; my=-16;
  5625.             cx=0; cy=2;
  5626.             }
  5627.         if(Cline>3 && Cline<8) {
  5628.             mx=16; my=0;
  5629.             cx=2; cy=0;
  5630.             }
  5631.         if(Cline>7 && Cline<12) {
  5632.             mx=0; my=16;
  5633.             cx=0; cy=2;
  5634.             Cline=11-(Cline-8);
  5635.             }
  5636.         if(Cline>11) {
  5637.             mx=-16; my=0;
  5638.             cx=2; cy=0;
  5639.             Cline=15-(Cline-12);
  5640.             }
  5641.  
  5642.         FindLineCount();
  5643.  
  5644.         while(GLine[Cline].count > 0) {
  5645.             Spr=LastOnLine(Cline+1);
  5646.             if(Spr!=0) {
  5647.                 s=&GSprite[Spr];
  5648.                 s->id=EXPLODE;
  5649.               s->walk=FALSE;
  5650.               s->oldx=0;
  5651.               s->oldy=0;
  5652.               s->xmov=0;
  5653.               s->ymov=0;
  5654.                 s->line=-1;
  5655.               SPRITENewAnim(Spr,0,0);
  5656.               s->animtime=2;
  5657.                 }
  5658.  
  5659.             for(i=1;i<NUMSPRITES;i++) {
  5660.                 s=&GSprite[i];
  5661.                 if(s->active==TRUE && ((s->id>=COLOR1 && s->id<=COLOR4) || (s->id>=BOMB1 && s->id<=BOMB3) ||
  5662.                    (s->id==BONUSB) ) && s->line==Cline+1) {
  5663.                     s->xmov=mx; s->ymov=my;
  5664.                     s->xcnt=cx; s->ycnt=cy;
  5665.                     }
  5666.                 }
  5667.             if(!DoneSound) {
  5668.                 //SoundPlay(10);
  5669.                 DoneSound=TRUE;
  5670.                 }
  5671.  
  5672.             for(j=0;j<2;j++) {
  5673.                 PANELUpdate();
  5674.                 GRAPHICUpdate();
  5675.               FindLineCount();
  5676.                 }
  5677.             }
  5678.         }
  5679.  
  5680.     for(j=0;j<24;j++) {
  5681.         PANELUpdate();
  5682.         GRAPHICUpdate();
  5683.         }
  5684.  
  5685.     //Tidy up any trivial sprites
  5686.       s=&GSprite[1];
  5687.       for(i=1;i<NUMSPRITES;i++) {
  5688.         if(s->active==TRUE && ((s->id>=COLOR1 && s->id<=COLOR4) || (s->id>=BOMB1 && s->id<=BOMB3) ||
  5689.             (s->id==BONUSB) )) {
  5690.           s->active=FALSE;
  5691.           }
  5692.         else {
  5693.           s->update=TRUE;
  5694.           s->forcedupdate=TRUE;
  5695.           s->oldx=0;
  5696.           s->oldy=0;
  5697.           }
  5698.         s++;
  5699.         }
  5700. }
  5701.  
  5702. //---------------------------------------------------------------------------
  5703.  
  5704. void NextLevelSequence()
  5705. {
  5706.       SPRITE *d1,*d2,*s;
  5707.       UWORD i;
  5708.       BOOL DoKill,DoFly;
  5709.  
  5710.     if( GPlayerMode != INMIDDLE ) return;
  5711.     if( LineState == BEING_BUILT ) return;
  5712.  
  5713.     FireEnableStatus=FALSE;
  5714.  
  5715.     for( i=0; i<32; i++ ) {
  5716.       GControlPlayer();
  5717.        MonitorWalking();
  5718.         PANELUpdate();
  5719.         GRAPHICUpdate();
  5720.         }
  5721.  
  5722.     if( Level >= MAXLEVELS && GameMode == CONTINUE ) {
  5723.         if( Level < 99 ) Level++;
  5724.         SetLevel(Level);
  5725.         GBKills=999;  //Make sure kills is updated (dummy value)
  5726.         FireEnableStatus=TRUE;
  5727.         return;
  5728.         }
  5729.  
  5730.       // Wait for beam to terminate
  5731.       DoKill=TRUE;
  5732.       while(DoKill==TRUE) {
  5733.       GControlPlayer();
  5734.         PANELUpdate();
  5735.         GRAPHICUpdate();
  5736.         DoKill=FALSE;
  5737.         for(i=1;i<NUMSPRITES;i++) {
  5738.           if((GSprite[i].active==TRUE) && (GSprite[i].id==LIGHTBEAM)) DoKill=TRUE;
  5739.           }
  5740.         }
  5741.  
  5742.     // Wait for flying sprites to finish
  5743.       DoFly=TRUE;
  5744.       while(DoFly==TRUE) {
  5745.       GControlPlayer();
  5746.         PANELUpdate();
  5747.         GRAPHICUpdate();
  5748.         DoFly=FALSE;
  5749.         for(i=1;i<NUMSPRITES;i++) {
  5750.           if((GSprite[i].active==TRUE) && (GSprite[i].dline!=NOLINE)) DoFly=TRUE;
  5751.           }
  5752.         }
  5753.  
  5754.     // Wait till player stops moving
  5755.     while( ((GSprite[0].x & 31) != 0) || ((GSprite[0].y & 31) != 0) ) {
  5756.         PANELUpdate();
  5757.        GRAPHICUpdate();
  5758.         }
  5759.     PANELUpdate();
  5760.    GRAPHICUpdate();
  5761.  
  5762.     //--New code: Remove strobe 5/9 jj-------------------------------------------
  5763.     if( NEWspr != -1 )
  5764.     {
  5765.         s = &GSprite[ NEWspr ];
  5766.  
  5767.         s->id=0;
  5768.         s->walk=FALSE;
  5769.         s->fly=FALSE;
  5770.         s->line=-1;
  5771.         s->xmov=0;
  5772.         s->ymov=0;
  5773.         s->oldx=0;
  5774.         s->oldy=0;
  5775.         s->clag=0;
  5776.         s->spawnid=-1;
  5777.         s->active=FALSE;
  5778.         NEWspr=-1;
  5779.         LineState = BUILT;
  5780.  
  5781.         AppearCount = 0;
  5782.     }
  5783.     //---------------------------------------------------------------------------
  5784.  
  5785.     SoundPlay(1);
  5786.  
  5787.     if( Level < 99 ) Level++;
  5788.       SetLevel(Level);
  5789.  
  5790.     if(GameMode==LEVELPLAY) {
  5791.         ShuffleOff();
  5792.         LineState = BEING_BUILT;
  5793.         }
  5794.     else {
  5795.           s=&GSprite[1];
  5796.           for(i=1;i<NUMSPRITES;i++) {
  5797.             // None Destructive next level
  5798.             if(s->active==TRUE && ((s->id>=EXPLODE && s->id<=LINEBONUS)) && (s->id != STROBE) ) {
  5799.               s->active=FALSE;
  5800.               }
  5801.             else {
  5802.               s->update=TRUE;
  5803.               s->forcedupdate=TRUE;
  5804.               s->oldx=0;
  5805.               s->oldy=0;
  5806.               }
  5807.             s++;
  5808.             }
  5809.         }
  5810.  
  5811.     FindLineCount();
  5812.  
  5813.     PANELUpdate();
  5814.    GRAPHICUpdate();
  5815.  
  5816.    StrobeVal1=0;
  5817.    SPal(StrobeColor1,StrobeR1,StrobeG1,StrobeB1);
  5818.    StrobeVal2=0;
  5819.    SPal(StrobeColor2,StrobeR1,StrobeG2,StrobeB2);
  5820.     StrobeSound=0;
  5821.  
  5822.     if( NET_Game == 0 ) {
  5823.         BackPcx.palette[ NET_Back_Color * 3 ] = 0;
  5824.         BackPcx.palette[ NET_Back_Color * 3 + 1 ] = 0;
  5825.         BackPcx.palette[ NET_Back_Color * 3 + 2 ] = 0;
  5826.         }
  5827.     SetPal((UBYTE *) BackPcx.palette);
  5828.  
  5829.     if(Level < 11) RectGrow();
  5830.  
  5831.     GSprite[0].forcedupdate=TRUE;
  5832.  
  5833.     GBKills=999;  //Make sure kills is updated (dummy value)
  5834.  
  5835.     if(GameMode==LEVELPLAY) CreateEnemyLeadIn();
  5836.  
  5837.     FireEnableStatus=TRUE;
  5838. }
  5839.  
  5840. //===========================================================================
  5841. // Network message handling
  5842. //===========================================================================
  5843.  
  5844. void Net_Check_Message()
  5845. {
  5846.     DWORD receive;
  5847.  
  5848.     if( GameMode != MULTI ) return;
  5849.  
  5850.     if( ! NETCheckEvent() ) return;
  5851.  
  5852.     receive = NETFindPlayerFrom();
  5853.  
  5854.     switch( NET_Player_Event ) {
  5855.         case 'A':
  5856.             BlockAddAmount = NET_Player_Value;
  5857.             BlockAddColor = ( rand() & 3 );
  5858.             EVENT_AddBlock++;
  5859.             if( receive != -1 ) NETReceiveArrows( receive );
  5860.             break;
  5861.         case 'B':
  5862.             EVENT_BlowUp++;
  5863.             if( receive != -1 ) NETReceiveArrows( receive );
  5864.             break;
  5865.         case 'C':
  5866.             SpeedUpDuration = 100;
  5867.             EVENT_SpeedUp++;
  5868.             if( receive != -1 ) NETReceiveArrows( receive );
  5869.             break;
  5870.         case 'D':
  5871.             EVENT_AddTarget++;
  5872.             break;
  5873.         }
  5874. }
  5875.  
  5876. //===========================================================================
  5877. // Pre-Game setup function
  5878. //===========================================================================
  5879.  
  5880. void PrepareToPlay()
  5881. {
  5882.     DWORD i;
  5883.  
  5884.     BlackPal();
  5885.       Svga.Cls();
  5886.       GSetup();
  5887.       PlayerSetup();
  5888.       ScoreSetup();
  5889.       SpringSetup();
  5890.  
  5891.     if( NET_Game == 1 ) NetSpriteSetup();
  5892.  
  5893.       Svga.Cls();
  5894.     memset(buf1,0,307200);
  5895.     memset(buf2,0,307200);
  5896.  
  5897.     for(i=0;i<NUMSPRITES;i++) {
  5898.         if(GSprite[i].active==TRUE) {
  5899.             GSprite[i].forcedupdate=TRUE;
  5900.             }
  5901.         }
  5902.  
  5903.     if( NET_Game == 1 ) {
  5904.         NETSetPlayerLevelSprings();
  5905.         EVENT_AddTarget = NET_Player_Springs;
  5906.         Level = NET_Player_Level+1;
  5907.         EnemyLeadIn = NET_Player_Blocks;
  5908.         }
  5909.  
  5910.     if( NET_Game == 0 ) {
  5911.         BackPcx.palette[ NET_Back_Color * 3 ] = 0;
  5912.         BackPcx.palette[ NET_Back_Color * 3 + 1 ] = 0;
  5913.         BackPcx.palette[ NET_Back_Color * 3 + 2 ] = 0;
  5914.         }
  5915.  
  5916.     SetPal((UBYTE *) BackPcx.palette);
  5917.     RectGrow();
  5918.     CreateEnemyLeadIn();
  5919. }
  5920.  
  5921. //===========================================================================
  5922. // Configuration file functions
  5923. //===========================================================================
  5924.  
  5925. void SetAdjustables()
  5926. {
  5927.     PlayerSpeed = 4;
  5928.     PlayerMoveBy = 32 / PlayerSpeed;
  5929.     DetailLevel = 0;
  5930. }
  5931.  
  5932. //===========================================================================
  5933. // Game over circle transition
  5934. //===========================================================================
  5935.  
  5936. void CreateCircleTable (DWORD xc, DWORD yc, DWORD r, WORD * table)
  5937. {
  5938.    WORD * buffer = table;
  5939.  
  5940.    for (DWORD i = 448; i > 0; i --)
  5941.       * buffer ++ = 320;
  5942.  
  5943.    DWORD x = 0,
  5944.        y = r;
  5945.  
  5946.    DWORD k = r * r;
  5947.  
  5948.    DWORD t = -2 * r * k + k,
  5949.        t1 = 4 * k - 4 * r * k,
  5950.        t2 = 2 * k;
  5951.  
  5952.    DWORD i1 = yc - y,
  5953.        i2 = yc + y,
  5954.        i3 = yc - x,
  5955.        i4 = yc + x;
  5956.  
  5957.    DWORD v1 = xc - x,
  5958.        v2 = xc - y;
  5959.  
  5960.    for (; x <= y; x ++)
  5961.       {
  5962.       if (i1 >= 0)
  5963.          * (table + i1) = v1;
  5964.  
  5965.       if (i2 < 448)
  5966.          * (table + i2) = v1;
  5967.  
  5968.       if (i3 >= 0)
  5969.          * (table + i3) = v2;
  5970.  
  5971.       if (i4 < 448)
  5972.          * (table + i4) = v2;
  5973.  
  5974.       if (t >= 0)
  5975.          {
  5976.          t += t1;
  5977.          y --;
  5978.          i1 ++;
  5979.          i2 --;
  5980.          v2 ++;
  5981.          t1 += 4 * r * r;
  5982.          }
  5983.  
  5984.       t += t2;
  5985.       t2 += 4 * r * r;
  5986.       i3 --;
  5987.       i4 ++;
  5988.       v1 --;
  5989.       }
  5990.  
  5991.    for (i = 448; i > 0; i --)
  5992.       {
  5993.       buffer --;
  5994.       if (* buffer < 0)
  5995.          * buffer = 0;
  5996.       }
  5997. }
  5998.  
  5999. //---------------------------------------------------------------------------
  6000.  
  6001. UDWORD CircA[448*2];
  6002.  
  6003. void LoseSequence()
  6004. {
  6005.     DWORD i;
  6006.     WORD * table_lt, * table_rt;
  6007.  
  6008.     for( i=0; i < NUMSPRITES; i++) GSprite[i].animtog = FALSE;
  6009.  
  6010.     for( i=0; i<64; i++ ) NET_Update();
  6011.  
  6012.     if( NET_Game == 0 ) BackPcx.Load("gfx\\endscr.imx",buf3);
  6013.     else BackPcx.Load("gfx\\lose.imx",buf3);
  6014.  
  6015.     memcpy(buf2,buf3,307200);
  6016.    SPRITEResetAll();
  6017.       MAPUpdateSetup();
  6018.  
  6019.    table_lt = (WORD *) CircA;    // Memory for the table(s)
  6020.  
  6021.    table_rt = table_lt + 448;
  6022.  
  6023.    for ( i = 0; i < 448; i ++)
  6024.       * (table_lt + i) = 0;
  6025.  
  6026.    for (DWORD r = 400; r > 0; r -= 8)                     // Radius of growing circle 0 -> 400
  6027.       {
  6028.         NET_Update();
  6029.         CreateCircleTable(320, 224, r, table_rt);          // Determine which bits of circle need plotting
  6030.  
  6031.       WaitTimer();
  6032.         MAPRefresh();
  6033.  
  6034.       WORD * buff2 = table_lt,
  6035.             * buff1 = table_rt;
  6036.  
  6037.       for (DWORD y = 0; y < 448; y ++)                     // For each line of the display
  6038.          {
  6039.             DWORD x=*buff2;
  6040.             DWORD w=(*buff1) - (*buff2);
  6041.  
  6042.             if(w>0 && w<320) THorzCopy(x,y,w);
  6043.  
  6044.             x=640 - *buff1;
  6045.             w=(640 - *buff2) - x;
  6046.             if(w>0 && w<320) THorzCopy(x,y,w);
  6047.  
  6048.          buff1 ++;
  6049.          buff2 ++;
  6050.          }
  6051.  
  6052.       WORD * spare = table_lt;
  6053.       table_lt = table_rt;
  6054.       table_rt = spare;
  6055.  
  6056.         BACKMapRefresh();
  6057.       }
  6058.     Copy2SvgaArea(buf3);
  6059.  
  6060.     if( NET_Game == 1 ) {
  6061.         while( NETFindGamePlayer() ) {
  6062.             WaitTimer();
  6063.             NET_Update();
  6064.             if(KEY[1]) {
  6065.                 while(KEY[1]);
  6066.                 break;
  6067.                 }
  6068.             if(KEY[K_FIRE]) {
  6069.                 while(KEY[K_FIRE]);
  6070.                 break;
  6071.                 }
  6072.             if(KEY[K_RETURN]) {
  6073.                 while(KEY[K_RETURN]);
  6074.                 break;
  6075.                 }
  6076.             }
  6077.         }
  6078.     else {
  6079.         for(i=0;i<120;i++) {
  6080.             WaitTimer();
  6081.             if(KEY[1]) {
  6082.                 while(KEY[1]);
  6083.                 break;
  6084.                 }
  6085.             if(KEY[K_FIRE]) {
  6086.                 while(KEY[K_FIRE]);
  6087.                 break;
  6088.                 }
  6089.             if(KEY[K_RETURN]) {
  6090.                 while(KEY[K_RETURN]);
  6091.                 break;
  6092.                 }
  6093.             }
  6094.         }
  6095. }
  6096.  
  6097. //---------------------------------------------------------------------------
  6098.  
  6099. void WinSequence()
  6100. {
  6101.     DWORD i;
  6102.     WORD * table_lt, * table_rt;
  6103.  
  6104.     NET_Player_Wins++;
  6105.  
  6106.     for( i=0; i < NUMSPRITES; i++) GSprite[i].animtog = FALSE;
  6107.  
  6108.     for( i=0; i<64; i++ ) NET_Update();
  6109.  
  6110.       BackPcx.Load("gfx\\win.imx",buf3);
  6111.     memcpy(buf2,buf3,307200);
  6112.    SPRITEResetAll();
  6113.       MAPUpdateSetup();
  6114.  
  6115.    table_lt = (WORD *) CircA;    // Memory for the table(s)
  6116.  
  6117.    table_rt = table_lt + 448;
  6118.  
  6119.    for ( i = 0; i < 448; i ++)
  6120.       * (table_lt + i) = 0;
  6121.  
  6122.    for (DWORD r = 400; r > 0; r -= 8)                     // Radius of growing circle 0 -> 400
  6123.       {
  6124.         NET_Update();
  6125.       CreateCircleTable(320, 224, r, table_rt);          // Determine which bits of circle need plotting
  6126.  
  6127.       WaitTimer();
  6128.         MAPRefresh();
  6129.  
  6130.       WORD * buff2 = table_lt,
  6131.             * buff1 = table_rt;
  6132.  
  6133.       for (DWORD y = 0; y < 448; y ++)                     // For each line of the display
  6134.          {
  6135.             DWORD x=*buff2;
  6136.             DWORD w=(*buff1) - (*buff2);
  6137.  
  6138.             if(w>0 && w<320) THorzCopy(x,y,w);
  6139.  
  6140.             x=640 - *buff1;
  6141.             w=(640 - *buff2) - x;
  6142.             if(w>0 && w<320) THorzCopy(x,y,w);
  6143.  
  6144.          buff1 ++;
  6145.          buff2 ++;
  6146.  
  6147.          }
  6148.  
  6149.       WORD * spare = table_lt;
  6150.       table_lt = table_rt;
  6151.       table_rt = spare;
  6152.  
  6153.         BACKMapRefresh();
  6154.       }
  6155.     Copy2SvgaArea(buf3);
  6156.  
  6157.     for(i=0;i<210;i++) {
  6158.         WaitTimer();
  6159.         NET_Update();
  6160.         if(KEY[1]) {
  6161.             while(KEY[1]);
  6162.             break;
  6163.             }
  6164.         if(KEY[K_FIRE]) {
  6165.             while(KEY[K_FIRE]);
  6166.             break;
  6167.             }
  6168.         if(KEY[K_RETURN]) {
  6169.             while(KEY[K_RETURN]);
  6170.             break;
  6171.             }
  6172.         }
  6173. }
  6174.  
  6175. //===========================================================================
  6176. // I/O Setup
  6177. //===========================================================================
  6178.  
  6179. void SetupJoystick()
  6180. {
  6181.     JOYTime();
  6182.  
  6183.     for( UDWORD i=0; i<256; i++ ) {
  6184.         JOYRead( Joy );
  6185.         JoyNormalx = Joy.JOY1x;
  6186.         JoyNormaly = Joy.JOY1y;
  6187.         }
  6188. }
  6189.  
  6190. //===========================================================================
  6191. // Zoop game sequence
  6192. //===========================================================================
  6193.  
  6194. extern void ContinueKey();
  6195. extern void BootUp();
  6196. extern UWORD TitleSequence();
  6197. extern UWORD HiScoreSequence();
  6198.  
  6199. void Zoop()
  6200. {
  6201.     BOOL QuitGame, Win, Slow;
  6202.       UWORD Option,i,KRepeat;
  6203.  
  6204.       QuitGame=FALSE;
  6205.  
  6206.     Level=1;
  6207.  
  6208.     Option=TitleSequence();
  6209.  
  6210.     if(Option==9) QuitGame=TRUE;
  6211.  
  6212.     switch( GameMode ) {
  6213.         case CONTINUE:
  6214.             LevelSet=LevelCon;
  6215.             DifficultySet=DifficultyCon;
  6216.             NET_Game = 0;
  6217.             break;
  6218.         case LEVELPLAY:
  6219.             LevelSet=LevelLev;
  6220.             DifficultySet=DifficultyLev;
  6221.             NET_Game = 0;
  6222.             break;
  6223.         case MULTI:
  6224.             LevelSet=LevelNet;
  6225.             DifficultySet=0;
  6226.             NET_Game = 1;
  6227.         }
  6228.  
  6229.     MusicEnd();
  6230.  
  6231.     KRepeat = 0;
  6232.  
  6233.       while(QuitGame==FALSE) {
  6234.         UWORD OldScore=-1,OldLevel=-1,OldKills=-1;
  6235.  
  6236.         if( NET_Game == 1 ) {
  6237.             NETSetPlayerLevelSprings();
  6238.             Level = NET_Player_Level+1;
  6239.             }
  6240.  
  6241.         SetLevel(Level);
  6242.         PrepareToPlay();  //Playersetup + fadeon etc
  6243.  
  6244.         StartGameClock();
  6245.  
  6246.         GGameOver=FALSE;
  6247.  
  6248.         Slow = 0;
  6249.  
  6250.         while(KEY[1]!=TRUE && GGameOver!=TRUE) {
  6251.  
  6252.             NET_Player_Type = NET_GAME_PLAYER;
  6253.  
  6254.             for( i=0; i<Slow; i++ ) WaitTimer();
  6255.  
  6256.             GRAPHICUpdate();
  6257.           FindLineCount();
  6258.             PANELUpdate();
  6259.  
  6260.             CreateEnemy();
  6261.           NewEnemy();
  6262.           EnemyAppear();
  6263.           MonitorWalking();
  6264.  
  6265.             Net_Check_Message();
  6266.             Net_Refresh_Names();
  6267.  
  6268.             Event_Bonus();
  6269.             Event_AddBlock();
  6270.             Event_SpeedUp();
  6271.             Event_AddTarget();
  6272.             Event_BlowUp();
  6273.  
  6274.             Event_Pause();
  6275.  
  6276.             if( KRepeat == 0 ) {
  6277.                 //Cheats
  6278.                 if(KEY[63]==TRUE) Kills=0;
  6279.                 if(KEY[59]==TRUE) {
  6280.                     KRepeat = 10;
  6281.                     BlockAddAmount = 5;
  6282.                     BlockAddColor = 1;
  6283.                     EVENT_AddBlock++;
  6284.                     }
  6285.                 if(KEY[60]==TRUE) {
  6286.                     KRepeat = 10;
  6287.                     EVENT_SpeedUp++;
  6288.                     }
  6289.                 if(KEY[61]==TRUE) {
  6290.                     KRepeat = 10;
  6291.                     EVENT_BlowUp++;
  6292.                     }
  6293.                 if(KEY[62]==TRUE) {
  6294.                     KRepeat = 10;
  6295.                     EVENT_AddTarget++;
  6296.                     }
  6297.                 if(KEY[64]==TRUE) {
  6298.                     KRepeat = 10;
  6299.                     if( Slow == 0 ) Slow = 2;
  6300.                     else Slow = 0;
  6301.                     }
  6302.                 } else KRepeat--;
  6303.  
  6304.             if( Kills<1 ) NextLevelSequence();
  6305.  
  6306.           GGameOver = GCheckGameOver();
  6307.           if( GGameOver == FALSE ) GControlPlayer();
  6308.           if( CheckPause() == TRUE ) EVENT_Pause = TRUE; //GamePause();
  6309.  
  6310.             Win = Net_Check_Won();
  6311.             if( Win ) GGameOver = TRUE;
  6312.             }
  6313.  
  6314.         FormatTime( GetGameClock(), HiTime );
  6315.  
  6316.         NET_Player_Type = NET_LOG_PLAYER;
  6317.  
  6318.         if( Win ) WinPlayer();
  6319.         else KillPlayer();
  6320.  
  6321.         for(i=0;i<20;i++)
  6322.             WaitTimer();
  6323.  
  6324.         MusicPlay(28);
  6325.  
  6326.         if( Win ) WinSequence();
  6327.         else LoseSequence();
  6328.  
  6329.         SetForFadeOut(0,256);
  6330.         MorphPal(0,255,2,APalette);
  6331.  
  6332.         if( NET_Game == 0 ) {
  6333.             i=HiScoreSequence();
  6334.             switch(i) {
  6335.                 case 1:
  6336.                     Level=LastLevel;
  6337.                     Difficulty=LastDifficulty;
  6338.                     if(GameMode==CONTINUE) LevelSet=LevelCon;
  6339.                     else LevelSet=LevelLev;
  6340.                     break;
  6341.                 case 2: // Exit from hiscore - go back to title
  6342.                     Level=1;
  6343.                     Option=TitleSequence();
  6344.                     if(Option==9) QuitGame=TRUE;
  6345.  
  6346.                     switch( GameMode ) {
  6347.                         case CONTINUE:
  6348.                             LevelSet=LevelCon;
  6349.                             DifficultySet=DifficultyCon;
  6350.                             NET_Game = 0;
  6351.                             break;
  6352.                         case LEVELPLAY:
  6353.                             LevelSet=LevelLev;
  6354.                             DifficultySet=DifficultyLev;
  6355.                             NET_Game = 0;
  6356.                             break;
  6357.                         case MULTI:
  6358.                             LevelSet=LevelNet;
  6359.                             DifficultySet=0;
  6360.                             NET_Game = 1;
  6361.                         }
  6362.                 }
  6363.             }
  6364.         else {
  6365.             Option=TitleSequence();
  6366.  
  6367.             if(Option==9) QuitGame=TRUE;
  6368.  
  6369.             switch( GameMode ) {
  6370.                 case CONTINUE:
  6371.                     LevelSet=LevelCon;
  6372.                     DifficultySet=DifficultyCon;
  6373.                     NET_Game = 0;
  6374.                     break;
  6375.                 case LEVELPLAY:
  6376.                     LevelSet=LevelLev;
  6377.                     DifficultySet=DifficultyLev;
  6378.                     NET_Game = 0;
  6379.                     break;
  6380.                 case MULTI:
  6381.                     LevelSet=LevelNet;
  6382.                     DifficultySet=0;
  6383.                     NET_Game = 1;
  6384.                 }
  6385.             }
  6386.         }
  6387. }
  6388.  
  6389. //===========================================================================
  6390. // Zoop main
  6391. //===========================================================================
  6392.  
  6393. BOOL CheckUV;
  6394. extern void ReadConfig();
  6395.  
  6396. void main(int argc, char *argv[])
  6397. {
  6398.     UWORD i,k;
  6399.  
  6400.     MOUSEReset();
  6401.     SetupJoystick();
  6402.  
  6403.     SoundFx=TRUE;
  6404.     SoundMusic=TRUE;
  6405.     Difficulty=1;
  6406.  
  6407.     // Randomize
  6408.       time_t tod;
  6409.       time(&tod);
  6410.       srand(tod);
  6411.  
  6412.       Svga.VesaFirst=TRUE;
  6413.  
  6414.     printf("\n\nGeneral MIDI timbres for Yamaha OPL-2 and OPL-3 based sound cards were produced\n");
  6415.     printf("by The Fat Man(TM) and developed by K.Weston Phelan and George Alistair Sanger.\n");
  6416.     printf("Copyright 1993, The Fat Man(TM)\n");
  6417.  
  6418.     FILE *fuv = fopen( "univbe.drv", "r" );
  6419.     if( fuv == NULL ) {
  6420.         CheckUV = FALSE;
  6421.         delay( 60 );
  6422.         }
  6423.     else {
  6424.         CheckUV = TRUE;
  6425.         fclose( fuv );
  6426.         }
  6427.  
  6428.     if( CheckUV ) {
  6429.         if( UV_install( "", TRUE ) != TRUE ) {
  6430.              printf("UNIVBE Not installed. To run ZOOP(tm) refer to README.TXT\n");
  6431.             exit( 1 );
  6432.             }
  6433.         }
  6434.  
  6435.       if(!Svga.Init()) {
  6436.        printf("\nVideo Card is not VESA compliant. To run ZOOP(tm) refer to README.TXT\n");
  6437.         exit( 1 );
  6438.         }
  6439.  
  6440.       if(GFXCas.Load("gfx\\zoop.out")==FALSE) {
  6441.         printf("\nCannot find file zoop.out\n");
  6442.         exit( 1 );
  6443.         }
  6444.  
  6445.       memset(buf1,0,307200);
  6446.       memset(buf2,0,307200);
  6447.       memset(buf3,0,307200);
  6448.  
  6449.     SetAdjustables();
  6450.  
  6451.     if( NETInit() == 0 ) {
  6452.         NET_Installed = FALSE;
  6453.         }
  6454.     else {
  6455.         NET_Installed = TRUE;
  6456.         printf("\nNetwork card has been found.\n");
  6457.  
  6458.         NETSetLookWait( 16 );
  6459.         NETSetPulseWait( 32 );
  6460.         NETPlayerInit();
  6461.         }
  6462.  
  6463.     SoundInit();
  6464.  
  6465.     TimerSetup();
  6466.  
  6467.     SoundLoad("sfx\\sfx00.xmi",0);
  6468.     SoundLoad("sfx\\sfx01.xmi",0);
  6469.     SoundLoad("sfx\\sfx02.xmi",0);
  6470.     SoundLoad("sfx\\sfx03.xmi",0);
  6471.     SoundLoad("sfx\\sfx04.xmi",0);
  6472.     SoundLoad("sfx\\sfx05.xmi",0);
  6473.     SoundLoad("sfx\\sfx06.xmi",0);
  6474.     SoundLoad("sfx\\sfx07.xmi",0);
  6475.     SoundLoad("sfx\\sfx08.xmi",0);
  6476.     SoundLoad("sfx\\sfx09.xmi",0);
  6477.     SoundLoad("sfx\\sfx10.xmi",0);
  6478.     SoundLoad("sfx\\sfx11.xmi",0);
  6479.     SoundLoad("sfx\\sfx12.xmi",0);
  6480.     SoundLoad("sfx\\sfx13.xmi",0);
  6481.     SoundLoad("sfx\\sfx14.xmi",0);
  6482.     SoundLoad("sfx\\sfx15.xmi",0);
  6483.     SoundLoad("sfx\\sfx16.xmi",0);
  6484.     SoundLoad("sfx\\sfx17.xmi",0);
  6485.     SoundLoad("sfx\\sfx18.xmi",0);
  6486.     SoundLoad("sfx\\sfx19.xmi",0);
  6487.     SoundLoad("sfx\\sfx20.xmi",0);
  6488.     SoundLoad("sfx\\sfx21.xmi",0);
  6489.     SoundLoad("sfx\\sfx22.xmi",0);
  6490.     SoundLoad("sfx\\sfx23.xmi",0);
  6491.      SoundLoad("sfx\\sfx24.xmi",0);
  6492.     SoundLoad("sfx\\sfx25.xmi",0);
  6493.     SoundLoad("sfx\\sfx26.xmi",0);
  6494.     SoundLoad("sfx\\sfx27.xmi",0);
  6495.  
  6496.     SoundLoad("sfx\\zoopjazz.xmi",0);
  6497.     SoundLoad("sfx\\jazz2.xmi",0);
  6498.     SoundLoad("sfx\\shake.xmi",0);
  6499.  
  6500.     SoundLoad("sfx\\tun1.xmi",0);
  6501.     SoundLoad("sfx\\tun2.xmi",0);
  6502.    SoundLoad("sfx\\tun3.xmi",0);
  6503.     SoundLoad("sfx\\tun4.xmi",0);
  6504.  
  6505.     MemAvail();
  6506.     printf("\n\nMemory: %s\n",MemFree);
  6507.  
  6508.       Svga.GraphOn640x480x256();
  6509.  
  6510.     GOBJ=GFXCas.OBJList;
  6511.  
  6512.       SetPal((UBYTE *) BackPcx.palette);
  6513.       Svga.Cls();
  6514.  
  6515.     KEYSetup();
  6516.       MAPUpdateSetup();
  6517.  
  6518.     ReadConfig();
  6519.  
  6520.      MusicPlay(28);
  6521.  
  6522.     BootUp();
  6523.  
  6524.     Zoop();
  6525.  
  6526.       SetForFadeOut(0,256);
  6527.       MorphPal(0,255,4,APalette);
  6528.  
  6529.     TimerKill();
  6530.  
  6531.     KEYReset();
  6532.  
  6533.     SoundFree();
  6534.  
  6535.     Svga.GraphOff640x480x256();
  6536.       Svga.Exit();
  6537.  
  6538.     if( NET_Installed ) NETFinish();
  6539.  
  6540.     UV_exit();
  6541.  
  6542.     exit( 0 );
  6543. }
  6544.