#include <mcomdf0-defs.h>


Prototype void cleanUp(int );
Prototype void fail(STRPTR);
Prototype void setExplosionBitMaps(void);
Prototype void moveExplosionList(void);
Prototype void startExplosion(UWORD,UWORD);
Prototype struct nodeExplode *endExplosion(struct nodeExplode *);
Prototype void moveGToAMissileList(void);
Prototype void startGToAMissile(UWORD,UWORD,UWORD);
Prototype struct nodeMissile *endGToAMissile(struct nodeMissile *);
Prototype void aimAToGMissile(UWORD,UWORD);
Prototype void moveAToGMissileList(void);
Prototype void startAToGMissile(UWORD,UWORD,UWORD,UWORD);
Prototype struct nodeMissile *endAToGMissile(struct nodeMissile *);
Prototype void destroyCity(WORD);
Prototype void extraCity(void);
Prototype void drawGround(void);
Prototype void startSprt(void);
Prototype void initSprt(struct nodeSprt *);
Prototype void moveSprtList(void);
Prototype struct nodeSprt *endSprt(struct nodeSprt *);
Prototype void ignoreSprt(struct nodeSprt *);
Prototype struct nodeSprt *destroySprt(struct nodeSprt *);
Prototype void startSat(void);
Prototype void initSat(struct nodeSprt *);
Prototype void moveSatList(void);
Prototype struct nodeSprt *endSat(struct nodeSprt *);
Prototype void ignoreSat(struct nodeSprt *);
Prototype struct nodeSprt *destroySat(struct nodeSprt *);



/***************************************
       SYSTEM GLOBAL VARIABLES
***************************************/
struct ColorMap *colorMap=NULL;
struct RastPort *screenRP=NULL,*viewRP=NULL;
struct AreaInfo areaInfo={0};
struct TmpRas tmpRas={0};
struct BitMap *viewBM,cityBM;

struct MsgPort *winMsgPort;

struct Library *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *MathIeeeSingBasBase;
struct Library *MathIeeeSingTransBase;
struct Library *DiskfontBase;
struct TextAttr topaz=
{
"army.font",9,NULL,NULL
};
extern __far struct Custom custom;
struct MsgPort *startPort;
struct UCopList *uCopList[2]={NULL};
struct ColorSpec baseColor;


struct ColorSpec cSpec[33]=
{
    {0,0,0,0},
    {1,0xF,0,0},
    {2,0,0xF,0},
    {3,0,0,0xF},
    {4,0xA,0xA,0},
    {5,0xA,0,0xA},
    {6,0,0xA,0xA},
    {7,0xF,0xF,0xF},
    {-1,0,0,0}
};

struct ColorSpec tCSpec[8];

struct TagItem screenTags[]=
{
    {SA_Left,0},
    {SA_Top,0},
    {SA_Width,320},
    {SA_Height,256},
    {SA_Depth,3},
    {SA_FullPalette,TRUE},
    {SA_Colors,(ULONG)cSpec},
    {SA_Font,(ULONG)&topaz},
    {SA_AutoScroll,TRUE},
    {TAG_DONE,NULL},
};

struct TagItem winTags[]=
{
    {WA_Left,0},
    {WA_Top,1},
    {WA_Width,310},
    {WA_Height,229},
    {WA_IDCMP,IDCMP_MOUSEBUTTONS|IDCMP_INTUITICKS|IDCMP_VANILLAKEY},
    {WA_CustomScreen,NULL},
    {WA_ReportMouse,TRUE},
    {WA_Borderless,TRUE},
    {WA_Activate,TRUE},
    {WA_RMBTrap,TRUE},
    {WA_SmartRefresh,TRUE},
    {TAG_DONE,NULL},
};
struct TagItem wTags[]=
{
    {WA_Left,0},
    {WA_Top,1},
    {WA_Width,310},
    {WA_Height,229},
    {WA_IDCMP,NULL},
    {WA_CustomScreen,NULL},
    {WA_SmartRefresh,TRUE},
    {TAG_DONE,NULL},
};

struct TagItem nwTags[]=
{
    {WA_Left,0},
    {WA_Top,1},
    {WA_Width,310},
    {WA_Height,229},
    {WA_IDCMP,IDCMP_VANILLAKEY|IDCMP_INTUITICKS},
    {WA_CustomScreen,NULL},
    {WA_Activate,TRUE},
    {WA_SmartRefresh,TRUE},
    {TAG_DONE,NULL},
};

struct Screen *screen=NULL;
struct Window *window=NULL;

WORD areaBuffer[100];
void *buffer;
struct RastPort explodRP[26];
struct BitMap	explodBM[26];
UBYTE *bytePtr;
/***************************************
	  GLOBAL VARIABLES
***************************************/
struct nodeExplode
{
struct nodeExplode *next,*prev;
UWORD x,y;
UBYTE stepCount;
}*head=NULL;

struct nodeMissile
{
struct nodeMissile *next,*prev;
ULONG stepCount;
WORD cX,cY,targetX,targetY;
WORD baseX,baseY,range;
WORD dX,dY;
}*GMHead=NULL,*AMHead=NULL;

struct nodeSprt
{
struct nodeSprt *next,*prev;
struct SimpleSprite *sprtF,*sprtR;
WORD sprtNoF,sprtNoR;
WORD direction;
UWORD *imageF,*imageR;
UBYTE exploding;
}*spHead=NULL,*saHead=NULL,*dHead=NULL;

struct hScore
{
ULONG hiScore;
char scoreStr[11],name[11];
}allTime[11],todays[11];

UWORD LplaneFront[]=
{
     0,0,
     0x0000,0x0000,0x0000,0x0000,
     0x0000,0x0000,0x0000,0x0000,
     0x0000,0x0000,0x0000,0x0000,
     0x0000,0x0001,0x003F,0x0000,
     0x03FF,0x0000,0x1DFF,0x0015,
     0x73FC,0x0003,0xFFFE,0x00E1,
     0x1FF8,0x0000,0x0000,0x0000,
     0x0000,0x0000,0x0000,0x0000,
     0x0000,0x0000,0x0000,0x0000,
     0x0000,0x0000,
     0,0
};

UWORD LplaneRear[]=
{    0,0,
     0x0000,0x0700,0x0000,0x0E00,
     0x0000,0x1C00,0x0002,0x3800,
     0x0007,0x7800,0x000E,0xF000,
     0x000F,0xF000,0xf81E,0x0000,
     0xFFFF,0x0000,0xFFFF,0x5500,
     0x7FFE,0x8000,0x3FFE,0xC000,
     0x07F0,0xE000,0x0000,0x7000,
     0x0000,0x3800,0x0000,0x1C00,
     0x0000,0x0E00,0x0000,0x0700,
     0x0000,0x0380,
     0,0
};

UWORD RplaneFront[]=
{
    0,0,
    0x0000,0x00E0,0x0000,0x0070,
    0x0000,0x0038,0x4000,0x001C,
    0xE000,0x001E,0x7000,0x000F,
    0xF000,0x000F,0x781F,0x0000,
    0xFFFF,0x0000,0xFFFF,0x00AA,
    0x7FFE,0x0001,0x7FFC,0x0003,
    0x0FE0,0x0007,0x0000,0x000E,
    0x0000,0x001C,0x0000,0x0038,
    0x0000,0x0070,0x0000,0x00E0,
    0x0000,0x01C0,
    0,0
};

UWORD RplaneRear[]=
{
    0,0,
    0x0000,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,
    0x0000,0x8000,0xFC00,0x0000,
    0xFFC0,0x0000,0xFFB8,0xA800,
    0x3FCE,0xC000,0x7FFF,0x8000,
    0x1FF8,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,
    0x0000,0x0000,
    0,0
};

UWORD sattalite[]=
{
    0,0,
    0x8001,0x0000,0x4002,0x0000,
    0x2004,0x0000,0x118B,0x0000,
    0x0FF0,0x0000,0x0E70,0x0180,
    0x0C30,0x03C0,0x1818,0x07E0,
    0x1818,0x07E0,0x0C30,0x03C0,
    0x0E70,0x0180,0x0FF0,0x0000,
    0x118B,0x0000,0x2004,0x0000,
    0x4002,0x0000,0x8001,0x0000,
    0,0
};

UWORD doodleBug[]=
{
    0,0,
    0x0000,0x0000,0x00F8,0x00F8,
    0x01BC,0x0104,0x02A2,0x0202,
    0x02FA,0x0202,0x022A,0x0202,
    0x01EC,0x0104,0x00F8,0x00F8,
    0,0
};

UWORD mouseImage[]=
{   0,0,
    0x0402,0x0402,0x0606,0x0204,
    0x030C,0x050A,0x0198,0x0294,
    0x00F0,0x0168,0x0060,0x0090,
    0x00F0,0x0090,0x0198,0x0168,
    0x030C,0x0294,0x0606,0x050A,
    0x0402,0x0204,0x0000,0x0402,
    0,0
};

UWORD crossImageData[][]=
{
    {0x0402,0x0606,0x030C,0x0198,
     0x00F0,0x0060,0x00F0,0x0198,
     0x030C,0x0606,0x0402,0x0000,
     0,0
    },
    {0x0402,0x0204,0x050A,0x0294,
     0x0168,0x0090,0x0090,0x0168,
     0x0294,0x050A,0x0204,0x0402
    }
};

struct Image crossImage=
{0,0,
 16,12,
 2,
(WORD *)crossImageData,3,0,
 NULL
};

ULONG cityImageData[2][16]=
{
    {0x00006000,0x00006000,0x00006000,0x00006000,
     0x00006000,0x00607800,0x00607800,0x00607830,
     0x0060F830,0x0661FC30,0x0661FC30,0x0763FCF0,
     0x07F3FEFC,0x3FFFFFFC,0x7FFFFFFF,0xFFFFFFFF,
    },
    {0x00000000,0x00000000,0x00000C00,0x000C8C00,
     0x000C8C00,0x000C8460,0x000C8460,0x000E8440,
     0x000E8440,0x000FCF40,0x300FCF40,0x330DCFC0,
     0x336DCDCC,0x036DCCCC,0x0FEDEFFC,0x7FFFFFFF,
    }
};

struct Image cityImage=
{
 0,0,
 32,16,
 2,
(WORD *) cityImageData,3,0,
 NULL
};

char allTimeText[10][30],todaysText[10][30],scoreStr[11];

struct IntuiText allTimeLine[10],todaysLine[10];
struct IntuiText startText=
{7,0,JAM1,0,0,NULL,"PRESS MOUSE BUTTON TO START",NULL};
struct IntuiText allTimeTitle=
{1,3,JAM2,0,0,NULL,"ALL TIME HI-SCORES",NULL};
struct IntuiText todaysTitle=
{3,4,JAM2,0,0,NULL,"TODAYS HI-SCORES",NULL};
struct IntuiText scoreText=
{3,4,JAM1,0,0,NULL,scoreStr,NULL};
struct IntuiText mouseQueryText=
{7,0,JAM1,0,0,NULL,"Does Your Mouse Have 3 Buttons ?",NULL};
struct IntuiText yesText=
{2,0,JAM1,0,0,NULL,"Y E S",NULL};
struct IntuiText noText=
{3,0,JAM1,0,0,NULL,"N O",NULL};
WORD count=1;
UBYTE baseCount=3;
ULONG level,wave,step,speed,score,eCity=2500;
BOOL city[12];
FILE *fp;
struct TextFont *font;
BOOL forbiden=FALSE,firstCall=TRUE;
struct MsgPort *replyPort,*audPort;

struct command
{
struct Message cMessage;
UBYTE command;
}audCommand;
BOOL threeMouseButtons=TRUE;
UBYTE shots[3];



/***************************************
		MAIN
***************************************/

void main(LONG argc,BYTE *argv)
{
WORD depth;
UWORD x=10,y=10;
ULONG count;
struct IntuiMessage *message;
BOOL waitFlag1,waitFlag2;
struct Window *allTimeWindow,*todaysWindow,*tWindow;
struct Screen *tScreen;

static UWORD colorTable[]=
{
0xFFF,0xF00,0x0F0,0x00F,
0x000,0xAA0,0xA0A,0x0AA
};

if(!(DiskfontBase=OpenLibrary("diskfont.library",37)))
    fail("Could not open disk font lib");

if(!(font=OpenDiskFont(&topaz)))
    fail("Could not get Font");


if(!(IntuitionBase=OpenLibrary("intuition.library",37)))
    fail("Could not open intuition library");


if(!(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37)))
    fail("Could not open graphics library");

if(!(MathIeeeSingBasBase=OpenLibrary("mathieeesingbas.library",37)))
    fail("Could not open math lib");

if(!(MathIeeeSingTransBase=OpenLibrary("mathieeesingtrans.library",37)))
    fail("Could not open maths lib");
/*system("resident shadow");*/
for(count=0;count<10;count++)
    {allTimeLine[count].FrontPen=3;
     allTimeLine[count].BackPen=4;
     allTimeLine[count].DrawMode=JAM1;
     allTimeLine[count].LeftEdge=0;
     allTimeLine[count].TopEdge=count*10;
     allTimeLine[count].ITextFont=NULL;
     allTimeLine[count].IText=allTimeText[count];
     allTimeLine[count].NextText=&allTimeLine[count+1];
     allTime[count].hiScore=0;
     strcpy(allTime[count].scoreStr,"        0");
     strcpy(allTime[count].name,"MARGINALLY");
     todaysLine[count].FrontPen=5;
     todaysLine[count].BackPen=6;
     todaysLine[count].DrawMode=JAM1;
     todaysLine[count].LeftEdge=0;
     todaysLine[count].TopEdge=count*10;
     todaysLine[count].ITextFont=NULL;
     todaysLine[count].IText=todaysText[count];
     todaysLine[count].NextText=&todaysLine[count+1];
    }
allTimeLine[9].NextText=NULL;
todaysLine[9].NextText=NULL;

hiScoreTables();
if(!(screen=OpenScreenTagList(NULL,screenTags)))
    fail("Could not open screen");
winTags[5].ti_Data=(ULONG)screen;
if(!(window=OpenWindowTagList(NULL,winTags)))
    fail("Could not open window1");
/*system("shadow");*/
PrintIText(window->RPort,&mouseQueryText,8,100);
Move(window->RPort,0,130);
Draw(window->RPort,320,130);
Move(window->RPort,160,130);
Draw(window->RPort,160,220);
PrintIText(window->RPort,&yesText,8,160);
PrintIText(window->RPort,&noText,168,160);

waitFlag1=TRUE;
while(waitFlag1)
    {Wait(1L<<(window->UserPort->mp_SigBit));
     message=(struct IntuiMessage *)GetMsg(window->UserPort);
     if(message->Class==IDCMP_MOUSEBUTTONS && message->MouseY>130)
	{if(message->MouseX>160)
	    threeMouseButtons=FALSE;
	 waitFlag1=FALSE;
	 ReplyMsg((struct Message *)message);
	}
    }

     for(count=0;count<26;count++)
	 {InitRastPort(&explodRP[count]);
	  InitBitMap(&explodBM[count],1,52,28);
	  explodRP[count].BitMap=&explodBM[count];
	  if(!(explodBM[count].Planes[0]=(PLANEPTR)AllocRaster(52,28)))
	    fail("Could not alloc explodBM Plane");
	  BltClear((UBYTE *)explodBM[count].Planes[0],(explodBM[count].BytesPerRow * explodBM[count].Rows),1L);
	 }
     if(!(buffer=AllocVec((window->RPort->BitMap->BytesPerRow * window->RPort->BitMap->Rows),MEMF_CLEAR)))
	 fail("could not alloc buffer for TmpRas");
     InitArea(&areaInfo,areaBuffer,40);
     InitTmpRas(&tmpRas,buffer,(window->RPort->BitMap->BytesPerRow * window->RPort->BitMap->Rows));
     setExplosionBitMaps();
setSounds();
/*system("shadow");*/
while(TRUE)
    {waitFlag1=TRUE;
     tScreen=screen;
     tWindow=window;
     if(!(screen=OpenScreenTagList(NULL,screenTags)))
	 fail("could not open screen");

     winTags[5].ti_Data=(ULONG)screen;
     wTags[5].ti_Data=(ULONG)screen;

     if(!(window=OpenWindowTagList(NULL,winTags)))
	 fail("Could not open window");
     viewRP=window->RPort;
     viewBM=viewRP->BitMap;
     shade();
     if(tWindow) CloseWindow(tWindow);
     if(tScreen) CloseScreen(tScreen);

     for(depth=0;depth<9;depth++)
	 city[depth]=TRUE;
     for(depth=0;depth<23;depth++)
	 PrintIText(viewRP,&startText,8,depth*10);
     /*system("shadow");*/
     count=0;
     while(waitFlag1)
	{waitFlag2=TRUE;
	 while(waitFlag2)
	    {ActivateWindow(window);
	     message=(struct IntuiMessage *)GetMsg(window->UserPort);
	     if(message)
		{if(message->Class & IDCMP_MOUSEBUTTONS)
		    waitFlag1=FALSE;
		 if(message->Class & IDCMP_INTUITICKS)
		    waitFlag2=FALSE;
		 if(message->Class & IDCMP_VANILLAKEY)
		    cleanUp(0);
		 ReplyMsg((struct Message *)message);
		}
	    }
	 count++;
	 count%=300;
	 if(!(count))
	    {
	     CloseWindow(todaysWindow);
	    }
	 else if(count==150)
	    {allTimeWindow=OpenWindowTagList(NULL,wTags);
	     SetRast(allTimeWindow->RPort,2);
	     PrintIText(allTimeWindow->RPort,&allTimeTitle,35,0);
	     PrintIText(allTimeWindow->RPort,allTimeLine,2,20);
	    }
	 else if(count==225)
	    {todaysWindow=OpenWindowTagList(NULL,wTags);
	     CloseWindow(allTimeWindow);
	     SetRast(todaysWindow->RPort,1);
	     PrintIText(todaysWindow->RPort,&todaysTitle,37,0);
	     PrintIText(todaysWindow->RPort,todaysLine,2,20);
	    }
	 if(!(rand()%15))
	    startAToGMissile(rand()%300,0,rand()%300,230);
	 if(!(rand()%60))
	    startSprt();
	 moveAToGMissileList();
	 moveExplosionList();
	 moveSprtList();
	 /*system("shadow");*/
	 if(!(rand()%45))
	    PrintIText(viewRP,&startText,8,rand()%23*10);
	 /*system("shadow");*/
	}

     while(AMHead)
	AMHead=endAToGMissile(AMHead);
     while(spHead)
	spHead=endSprt(spHead);
     while(head)
	head=endExplosion(head);
     score=0;
     if(threeMouseButtons)
	gameLoop1();
     else
	gameLoop2();
     theEnd();
     hiScoreTables();
     /*system("shadow");*/
    }

}

/***************************************
	FUNCTION DEFINITIONS
***************************************/

void fail(STRPTR errorString)
{
printf(errorString);
cleanUp(RETURN_FAIL);
}
/**************************************/

void cleanUp(int returnCode)
{
BYTE depth;
struct nodeExplode *tHead,*stHead;
struct nodeMissile *tGMHead,*stGMHead;
struct nodeSprt *tDHead,*stDHead,*tSPHead,*stSPHead;
if(fp) fclose(fp);
if(window) CloseWindow(window);
if(screen) CloseScreen(screen);
if(buffer) FreeVec(buffer);
for(depth=0;depth<2;depth++)
    {if(cityBM.Planes[depth])
	FreeRaster(cityBM.Planes[depth],32,16);
    }
tDHead=dHead;
while(tDHead)
	{stDHead=tDHead->next;
	 FreeSprite(stDHead->sprtNoF);
	 FreeSprite(stDHead->sprtNoR);
	 FreeVec(tDHead);
	 tDHead=stDHead;
	}
tSPHead=dHead;
while(tSPHead)
	{stSPHead=tSPHead->next;
	 FreeSprite(stSPHead->sprtNoF);
	 FreeSprite(stSPHead->sprtNoR);
	 FreeVec(tSPHead);
	 tSPHead=stSPHead;
	}
tDHead=dHead;
/*while(tSAHead)
	{stSAHead=tSAHead->next;
	 FreeSprite(stSAHead->sprtNoF);
	 FreeSprite(stSAHead->sprtNoR);
	 FreeVec(tSAHead);
	 tSAHead=stSAHead;
	}*/
if(MathIeeeSingBasBase) CloseLibrary(MathIeeeSingBasBase);
if(MathIeeeSingTransBase) CloseLibrary(MathIeeeSingTransBase);
if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if(GfxBase) CloseLibrary((struct Library *)GfxBase);

tHead=head;
while(tHead)
    {stHead=tHead->next;
     FreeVec(tHead);
     tHead=stHead;
    }

tGMHead=GMHead;
while(tGMHead)
    {stGMHead=tGMHead->next;
     FreeVec(tGMHead);
     tGMHead-stGMHead;
    }
printf("    %d  ",score);
exit(returnCode);
}
/**************************************/

void setExplosionBitMaps()
{
UBYTE count;
for(count=0;count<26;count++)
    {explodRP[count].AreaInfo=&areaInfo;
     explodRP[count].TmpRas=&tmpRas;
     if(count<14)
	{SetAPen(&explodRP[count],1);
	 AreaEllipse(&explodRP[count],26,13,count+count/2,count);
	 AreaEnd(&explodRP[count]);
	}
     else
	{SetAPen(&explodRP[count],1);
	 AreaEllipse(&explodRP[count],26,13,(27-count)+(27-count)/2,27-count);
	 AreaEnd(&explodRP[count]);
	}
    }
}
/**************************************/
void moveExplosionList()
{
struct nodeExplode *tHead;
if(head)
    {tHead=head;
     while(tHead)
	{if(tHead->stepCount<14)
	    {SetAPen(viewRP,7);
	     BltPattern(viewRP,explodBM[tHead->stepCount].Planes[0],tHead->x-26,tHead->y-13,tHead->x+26,tHead->y+13,explodBM[tHead->stepCount].BytesPerRow);
	    }
	 else
	    {SetAPen(viewRP,0);
	     BltPattern(viewRP,explodBM[tHead->stepCount-1].Planes[0],tHead->x-26,tHead->y-13,tHead->x+26,tHead->y+13,explodBM[tHead->stepCount-1].BytesPerRow);
	     SetAPen(viewRP,7);
	     if(tHead->stepCount<26)
		BltPattern(viewRP,explodBM[tHead->stepCount].Planes[0],tHead->x-26,tHead->y-13,tHead->x+26,tHead->y+13,explodBM[tHead->stepCount].BytesPerRow);
	    }
	 tHead->stepCount++;
	 if(tHead->stepCount>26)
	    tHead=endExplosion(tHead);
	 else
	    tHead=tHead->next;
	}
    }
}

/**************************************/

void startExplosion(UWORD x,UWORD y)
{
struct nodeExplode *tHead;
if(head)
    {tHead=head;
     while(tHead->next)
	tHead=tHead->next;
     if(!(tHead->next=(struct nodeExplode *)AllocVec(sizeof(struct nodeExplode),MEMF_ANY)))
	fail("Could not alloc explosion list");
     tHead->next->prev=tHead;
     tHead=tHead->next;
     tHead->next=NULL;
     tHead->x=x;
     tHead->y=y;
     tHead->stepCount=1;
    }
else
    {if(!(head=(struct nodeExplode *)AllocVec(sizeof(struct nodeExplode),MEMF_ANY)))
	fail("Could not alloc explosion list");
     head->next=NULL;
     head->prev=NULL;
     head->x=x;
     head->y=y;
     head->stepCount=1;
    }
}
/**************************************/

struct nodeExplode *endExplosion(struct nodeExplode *node)
{
struct nodeExplode *tNode;

if(node==head)
    {tNode=head=node->next;
     if(tNode)
	tNode->prev=NULL;
    }
else
    {tNode=node->next;
     if(tNode)
	tNode->prev=node->prev;
     node->prev->next=tNode;
    }
FreeVec(node);

return tNode;
}
/**************************************/

void startGToAMissile(UWORD base,UWORD x,UWORD y)
{
struct nodeMissile *tGMHead;
if(y>210) return;
if(!(city[base/35]))
    {if(!(base=altBase(base,x)))
	return;
    }
if(GMHead)
    {tGMHead=GMHead;
     while(tGMHead->next)
	tGMHead=tGMHead->next;
     if(!(tGMHead->next=(struct nodeMissile *)AllocVec(sizeof(struct nodeMissile),MEMF_ANY)))
	fail("Could not alloc GtoA missile list");
     tGMHead->next->prev=tGMHead;
     tGMHead=tGMHead->next;
     tGMHead->next=NULL;
     tGMHead->targetX=x;
     tGMHead->targetY=y;
     tGMHead->baseX=base;
     tGMHead->baseY=220;
     tGMHead->cX=tGMHead->baseX;
     tGMHead->cY=tGMHead->baseY;
     tGMHead->dX=tGMHead->targetX-tGMHead->baseX;
     tGMHead->dY=tGMHead->baseY-tGMHead->targetY;
     tGMHead->range=IEEESPSqrt((FLOAT)(tGMHead->dX*tGMHead->dX+tGMHead->dY*tGMHead->dY));
     tGMHead->stepCount=0;
    }
else
    {if(!(GMHead=(struct nodeMissile *)AllocVec(sizeof(struct nodeMissile),MEMF_ANY)))
	fail("Could not alloc GtoAir Head");
     GMHead->prev=NULL;
     GMHead->next=NULL;
     GMHead->targetX=x;
     GMHead->targetY=y;
     GMHead->baseX=base;
     GMHead->baseY=220;
     GMHead->cX=GMHead->baseX;
     GMHead->cY=GMHead->baseY;
     GMHead->dX=GMHead->targetX-GMHead->baseX;
     GMHead->dY=GMHead->baseY-GMHead->targetY;
     GMHead->range=IEEESPSqrt((FLOAT)(GMHead->dX*GMHead->dX+GMHead->dY*GMHead->dY));
     GMHead->stepCount=0;
    }
DrawImage(viewRP,&crossImage,x-10,y-6);
}
/**************************************/

void moveGToAMissileList()
{
struct nodeMissile *tGMHead;

if(GMHead)
    {tGMHead=GMHead;
     while(tGMHead)
	{SetAPen(viewRP,5);
	 WritePixel(viewRP,tGMHead->cX,tGMHead->cY);
	 tGMHead->stepCount+=5;
	 tGMHead->cY=tGMHead->baseY-((tGMHead->stepCount*tGMHead->dY)/tGMHead->range);
	 tGMHead->cX=((tGMHead->baseY-tGMHead->cY)*tGMHead->dX)/tGMHead->dY+tGMHead->baseX;
	 if(tGMHead->cY<=tGMHead->targetY)
	    tGMHead=endGToAMissile(tGMHead);
	 else
	    tGMHead=tGMHead->next;
	}

    }
}

/**************************************/

struct nodeMissile *endGToAMissile(struct nodeMissile *missile)
{
struct nodeMissile *tMissile;

SetAPen(viewRP,0);
Move(viewRP,missile->targetX,missile->targetY);
while(missile->cY<missile->baseY)
    {WritePixel(viewRP,missile->cX,missile->cY);
     missile->stepCount--;
     missile->cY=missile->baseY-((missile->stepCount*missile->dY)/missile->range);
     missile->cX=((missile->baseY-missile->cY)*missile->dX)/missile->dY+missile->baseX;
    }
startExplosion(missile->targetX,missile->targetY);
if(missile==GMHead)
    {tMissile=GMHead=missile->next;
     if(tMissile)
	tMissile->prev=NULL;
    }
else
    {tMissile=missile->next;
     if(tMissile)
	tMissile->prev=missile->prev;
     missile->prev->next=tMissile;
    }
FreeVec(missile);

return tMissile;
}
/**************************************/
void aimAToGMissile(UWORD startX,UWORD startY)
{
UBYTE targ;

targ=rand()%9;
switch(targ)
    {case 0:
	startAToGMissile(startX,startY,14,220);
	break;
     case 4:
	startAToGMissile(startX,startY,150,220);
	break;
     case 8:
	startAToGMissile(startX,startY,286,220);
	break;
     default:
	if(targ<4) startAToGMissile(startX,startY,36*targ+8,220);
	else startAToGMissile(startX,startY,36*targ,220);
	break;
    }
}
/**************************************/

void startAToGMissile(UWORD startX,UWORD startY,UWORD tagX,UWORD tagY)
{
struct nodeMissile *tAMHead;

if(AMHead)
    {tAMHead=AMHead;
     while(tAMHead->next)
	tAMHead=tAMHead->next;
     if(!(tAMHead->next=(struct nodeMissile *)AllocVec(sizeof(struct nodeMissile),MEMF_ANY)))
	fail("Could not alloc AtoG missile list");
     tAMHead->next->prev=tAMHead;
     tAMHead=tAMHead->next;
     tAMHead->next=NULL;
     tAMHead->targetX=tagX;
     tAMHead->targetY=tagY;
     tAMHead->baseX=startX;
     tAMHead->baseY=startY;
     tAMHead->cX=tAMHead->baseX;
     tAMHead->cY=tAMHead->baseY;
     tAMHead->dX=(WORD)(tAMHead->targetX-tAMHead->baseX);
     tAMHead->dY=tAMHead->targetY-tAMHead->baseY;
     tAMHead->range=(UWORD)IEEESPSqrt((FLOAT)(tAMHead->dX*tAMHead->dX+tAMHead->dY*tAMHead->dY));
     tAMHead->stepCount=0;
    }
else
    {if(!(AMHead=(struct nodeMissile *)AllocVec(sizeof(struct nodeMissile),MEMF_ANY)))
	fail("Could not alloc AirtoG Head");
     AMHead->prev=NULL;
     AMHead->next=NULL;
     AMHead->targetX=tagX;
     AMHead->targetY=tagY;
     AMHead->baseX=startX;
     AMHead->baseY=startY;
     AMHead->cX=AMHead->baseX;
     AMHead->cY=AMHead->baseY;
     AMHead->dX=(WORD)(AMHead->targetX-AMHead->baseX);
     AMHead->dY=AMHead->targetY-AMHead->baseY;
     AMHead->range=(UWORD)IEEESPSqrt((FLOAT)(AMHead->dX*AMHead->dX+AMHead->dY*AMHead->dY));
     AMHead->stepCount=0;
    }

}
/**************************************/
void moveAToGMissileList()
{
struct nodeMissile *tAMHead;

speed=level/14+1;
if(AMHead)
    {tAMHead=AMHead;
     while(tAMHead)
	{SetAPen(viewRP,6);
	 WritePixel(viewRP,tAMHead->cX,tAMHead->cY);
	 tAMHead->stepCount+=speed;
	 tAMHead->cY=tAMHead->baseY+((tAMHead->stepCount*tAMHead->dY)/tAMHead->range);
	 tAMHead->cX=((tAMHead->cY-tAMHead->baseY)*tAMHead->dX)/tAMHead->dY+tAMHead->baseX;
	 if(tAMHead->cY>=tAMHead->targetY)
	    {destroyCity(tAMHead->targetX);
	     tAMHead=endAToGMissile(tAMHead);
	    }
	 else if(ReadPixel(viewRP,tAMHead->cX,tAMHead->cY)==7)
		 {tAMHead=endAToGMissile(tAMHead);
		  triggerSound(2);
		 }

	      else
		 tAMHead=tAMHead->next;
	}

    }

}

/**************************************/
struct nodeMissile *endAToGMissile(struct nodeMissile *missile)
{
struct nodeMissile *tMissile;
UWORD eX,eY;

eX=missile->cX;
eY=missile->cY;
if(eY<220) score+=220-eY;
SetAPen(viewRP,0);
WritePixel(viewRP,missile->cX,missile->cY);
while(missile->cY>missile->baseY)
    {missile->stepCount-=level/20+1;
     missile->cY=missile->baseY+((missile->stepCount*missile->dY)/missile->range);
     missile->cX=((missile->cY-missile->baseY)*missile->dX)/missile->dY+missile->baseX;
     WritePixel(viewRP,missile->cX,missile->cY);
    }
startExplosion(eX,eY);
if(missile==AMHead)
    {AMHead=missile->next;
     tMissile=AMHead;
     if(tMissile)
	tMissile->prev=NULL;
    }
else
    {tMissile=missile->next;
     if(tMissile)
	tMissile->prev=missile->prev;
     missile->prev->next=tMissile;
    }
FreeVec(missile);

return tMissile;
}

/**************************************/
void destroyCity(WORD hit)
{
triggerSound(1);
switch(hit)
    {case 14:
	if(city[0])
	    baseCount--;
	city[0]=FALSE;
	break;
     case 150:
	if(city[4])
	    baseCount--;
	city[4]=FALSE;
	break;
     case 286:
	if(city[8])
	    baseCount--;
	city[8]=FALSE;
	break;
     default:
	if(hit<150) city[(hit-8)/36]=FALSE;
	else city[hit/36]=FALSE;
	break;
    }
}
/**************************************/
void extraCity()
{
UBYTE count;
count=rand()%6+1;
if(count=4) count=7;
if(city[count])
    {count=1;
     while(count<11 && city[count])
	 {count++;
	  if(count==4 || count==8) count++;
	 }
    }
city[count]=TRUE;
if(score>eCity) eCity*=2;
}

/**************************************/
void drawGround()
{
SetAPen(viewRP,4);
AreaMove(viewRP,0,228);
AreaDraw(viewRP,0,225);
AreaDraw(viewRP,10,220);
AreaDraw(viewRP,18,220);
AreaDraw(viewRP,28,225);
AreaDraw(viewRP,28,228);
AreaDraw(viewRP,0,228);
AreaEnd(viewRP);
AreaMove(viewRP,300,228);
AreaDraw(viewRP,300,225);
AreaDraw(viewRP,290,220);
AreaDraw(viewRP,282,220);
AreaDraw(viewRP,272,225);
AreaDraw(viewRP,272,228);
AreaDraw(viewRP,300,228);
AreaEnd(viewRP);
AreaMove(viewRP,136,228);
AreaDraw(viewRP,136,225);
AreaDraw(viewRP,146,220);
AreaDraw(viewRP,154,220);
AreaDraw(viewRP,164,225);
AreaDraw(viewRP,164,228);
AreaDraw(viewRP,136,228);
AreaEnd(viewRP);
}
/**************************************/
void startSprt()
{
struct nodeSprt *tSpHead;

if(spHead)
    {tSpHead=spHead;
     while(tSpHead->next)
	tSpHead=tSpHead->next;
     if(!(tSpHead->next=(struct nodeSprt *)AllocVec(sizeof(struct nodeSprt),MEMF_ANY)))
	fail("Could not alloc Sprt list");
     tSpHead->next->prev=tSpHead;
     tSpHead=tSpHead->next;
     tSpHead->next=NULL;
     initSprt(tSpHead);
    }
else
    {if(!(spHead=(struct nodeSprt *)AllocVec(sizeof(struct nodeSprt),MEMF_ANY)))
	fail("Could not alloc sprite list head");
     spHead->prev=NULL;
     spHead->next=NULL;
     initSprt(spHead);
    }
}
/**************************************/
void initSprt(struct nodeSprt *sprtPtr)
{
UBYTE height,count;
WORD direction;

height=rand()%100+10;
direction=(rand()%2)*300;

if(!(sprtPtr->sprtF=(struct SimpleSprite *)AllocVec(sizeof(struct SimpleSprite),MEMF_ANY)))
     fail("Could Not Alloc sprite struct");
if(!(sprtPtr->sprtR=(struct SimpleSprite *)AllocVec(sizeof(struct SimpleSprite),MEMF_ANY)))
     fail("Could Not Alloc sprite struct");
if(-1==(sprtPtr->sprtNoF=GetSprite(sprtPtr->sprtF,-1)))
    {ignoreSprt(sprtPtr);
     return;
    }
if(-1==(sprtPtr->sprtNoR=GetSprite(sprtPtr->sprtR,-1)))
    {ignoreSprt(sprtPtr);
     return;
    }
if(!(sprtPtr->imageF=(UWORD *)AllocVec((sizeof(UWORD))*42,MEMF_CHIP)))
    fail("Could not alloc SprtimageF");
if(!(sprtPtr->imageR=(UWORD *)AllocVec((sizeof(UWORD))*42,MEMF_CHIP)))
    fail("Could not alloc SprtimageR");
for(count=0;count<42;count++)
    {if(direction)
	{*(sprtPtr->imageF+count)=LplaneFront[count];
	 *(sprtPtr->imageR+count)=LplaneRear[count];
	}
     else
	{*(sprtPtr->imageF+count)=RplaneFront[count];
	 *(sprtPtr->imageR+count)=RplaneRear[count];
	}
    }
if(direction)
    {sprtPtr->sprtF->x=direction;
     sprtPtr->sprtR->x=316;
    }
else
    {sprtPtr->sprtR->x=16;
     sprtPtr->sprtF->x=direction;
    }
sprtPtr->sprtF->y=height;
sprtPtr->sprtF->height=20;
sprtPtr->sprtR->y=height;
sprtPtr->sprtR->height=20;
sprtPtr->direction=(direction/150-1)*-1;
sprtPtr->exploding=0;

ChangeSprite((struct ViewPort *)NULL,sprtPtr->sprtF,(APTR)sprtPtr->imageF);
ChangeSprite((struct ViewPort *)NULL,sprtPtr->sprtR,(APTR)sprtPtr->imageR);

}
/**************************************/

void moveSprtList()
{
struct nodeSprt *tSpHead;

tSpHead=spHead;
while(tSpHead)
    {if(tSpHead->exploding)
	{tSpHead->exploding++;
	 (UWORD)tSpHead->imageF[rand()%38+2]&=rand()%0xFFFF;
	 (UWORD)tSpHead->imageF[rand()%38+2]&=rand()%0xFFFF;
	 (UWORD)tSpHead->imageR[rand()%38+2]&=rand()%0xFFFF;
	 (UWORD)tSpHead->imageR[rand()%38+2]&=rand()%0xFFFF;
	 ChangeSprite(NULL,tSpHead->sprtF,(APTR)tSpHead->imageF);
	 ChangeSprite(NULL,tSpHead->sprtR,(APTR)tSpHead->imageR);
	 if(tSpHead->exploding>10)
	    tSpHead=destroySprt(tSpHead);
	 else
	    tSpHead=tSpHead->next;
	}
     else
	{MoveSprite(NULL,tSpHead->sprtF,tSpHead->sprtF->x+tSpHead->direction,tSpHead->sprtF->y);
	 MoveSprite(NULL,tSpHead->sprtR,tSpHead->sprtR->x+tSpHead->direction,tSpHead->sprtR->y);
	 if(!(rand()%250))
	    {while(rand()%(level/2+1))
		aimAToGMissile(tSpHead->sprtR->x,tSpHead->sprtF->y+12);
	    }

	 if(7==ReadPixel(viewRP,tSpHead->sprtF->x,tSpHead->sprtF->y+11))
	    {startExplosion(tSpHead->sprtF->x,tSpHead->sprtF->y+11);
	     triggerSound(2);
	     tSpHead->exploding=1;
	    }
	 else if(7==ReadPixel(viewRP,tSpHead->sprtR->x+16,tSpHead->sprtF->y+11))
	    {startExplosion(tSpHead->sprtR->x+16,tSpHead->sprtF->y+11);
	     triggerSound(2);
	     tSpHead->exploding=1;
	    }
	      else if(7==ReadPixel(viewRP,tSpHead->sprtR->x,tSpHead->sprtF->y))
		     {startExplosion(tSpHead->sprtR->x,tSpHead->sprtF->y);
		      triggerSound(2);
		      tSpHead->exploding=1;
		      }
		   else if(7==ReadPixel(viewRP,tSpHead->sprtR->x,tSpHead->sprtF->y+20))
			   {startExplosion(tSpHead->sprtR->x,tSpHead->sprtF->y+20);
			    triggerSound(2);
			    tSpHead->exploding=1;
			    }
	 if(tSpHead->sprtF->x>300)
	    tSpHead=endSprt(tSpHead);
	 else tSpHead=tSpHead->next;
	}
    }
}

/**************************************/
struct nodeSprt *endSprt(struct nodeSprt *sprtPtr)
{
struct nodeSprt *tNode;
if(sprtPtr==spHead)
    {spHead=sprtPtr->next;
     tNode=spHead;
     if(tNode)
	tNode->prev=NULL;
    }
else
    {tNode=sprtPtr->next;
     if(tNode)
	tNode->prev=sprtPtr->prev;
     sprtPtr->prev->next=tNode;
    }
FreeVec(sprtPtr->sprtF);
FreeVec(sprtPtr->sprtR);
FreeSprite(sprtPtr->sprtNoF);
FreeSprite(sprtPtr->sprtNoR);
FreeVec(sprtPtr);
return tNode;
}
/**************************************/
void ignoreSprt(struct nodeSprt *sprtPtr)
{
if(sprtPtr==spHead)
    spHead=NULL;
else
    sprtPtr->prev->next=NULL;
if(-1!=sprtPtr->sprtNoF) FreeSprite(sprtPtr->sprtNoF);
FreeVec(sprtPtr);
}

/**************************************/

struct nodeSprt *destroySprt(struct nodeSprt *sprtPtr)
{
triggerSound(2);
startExplosion(sprtPtr->sprtR->x,sprtPtr->sprtF->y+10);
score+=sprtPtr->sprtF->y;
sprtPtr=endSprt(sprtPtr);
return sprtPtr;
}
/**************************************/
void startSat()
{
struct nodeSprt *tSaHead;

if(saHead)
    {tSaHead=saHead;
     while(tSaHead->next)
	tSaHead=tSaHead->next;
     if(!(tSaHead->next=(struct nodeSprt *)AllocVec(sizeof(struct nodeSprt),MEMF_ANY)))
	fail("Could not alloc Sprt list");
     tSaHead->next->prev=tSaHead;
     tSaHead=tSaHead->next;
     tSaHead->next=NULL;
     initSat(tSaHead);
    }
else
    {if(!(saHead=(struct nodeSprt *)AllocVec(sizeof(struct nodeSprt),MEMF_ANY)))
	fail("Could not alloc sprite list head");
     saHead->prev=NULL;
     saHead->next=NULL;
     initSat(saHead);
    }
}
/**************************************/
void initSat(struct nodeSprt *sprtPtr)
{
UBYTE height,count;
WORD direction;

height=rand()%(level*5)+10;
direction=(rand()%2)*300;

if(!(sprtPtr->sprtF=(struct SimpleSprite *)AllocVec(sizeof(struct SimpleSprite),MEMF_ANY)))
     fail("Could Not Alloc sprite struct");
if(-1==(sprtPtr->sprtNoF=GetSprite(sprtPtr->sprtF,-1)))
    {ignoreSat(sprtPtr);
     return;
    }
if(!(sprtPtr->imageF=(UWORD *)AllocVec((sizeof(UWORD))*36,MEMF_CHIP)))
    fail("Could not alloc SprtimageF");
for(count=0;count<36;count++)
    *(sprtPtr->imageF+count)=sattalite[count];
sprtPtr->sprtF->x=direction;
sprtPtr->sprtF->y=height;
sprtPtr->sprtF->height=16;
sprtPtr->direction=(direction/150-1)*-2;
sprtPtr->exploding=0;

ChangeSprite(NULL,sprtPtr->sprtF,(APTR)sprtPtr->imageF);

}
/**************************************/

void moveSatList()
{
struct nodeSprt *tSaHead;

tSaHead=saHead;
while(tSaHead)
    {if(tSaHead->exploding)
	{tSaHead->exploding++;
	 (UWORD)tSaHead->imageF[rand()%32+2]&=rand()%0xFFFF;
	 (UWORD)tSaHead->imageF[rand()%32+2]&=rand()%0xFFFF;
	 ChangeSprite(NULL,tSaHead->sprtF,(APTR)tSaHead->imageF);
	 if(tSaHead->exploding>10)
	    tSaHead=destroySat(tSaHead);
	 else
	    tSaHead=tSaHead->next;
	}
     else
	{MoveSprite(NULL,tSaHead->sprtF,tSaHead->sprtF->x+tSaHead->direction,tSaHead->sprtF->y);
	 if(!(rand()%(140/level)))
		aimAToGMissile(tSaHead->sprtF->x,tSaHead->sprtF->y+12);

	 if(7==ReadPixel(viewRP,tSaHead->sprtF->x,tSaHead->sprtF->y))
	    {startExplosion(tSaHead->sprtF->x,tSaHead->sprtF->y);
	     triggerSound(2);
	     tSaHead->exploding=1;
	    }
	 else if(7==ReadPixel(viewRP,tSaHead->sprtF->x+16,tSaHead->sprtF->y))
	    {startExplosion(tSaHead->sprtF->x+16,tSaHead->sprtF->y);
	     triggerSound(2);
	     tSaHead->exploding=1;
	    }
	      else if(7==ReadPixel(viewRP,tSaHead->sprtF->x,tSaHead->sprtF->y+16))
		     {startExplosion(tSaHead->sprtF->x,tSaHead->sprtF->y+16);
		      triggerSound(2);
		      tSaHead->exploding=1;
		      }
		   else if(7==ReadPixel(viewRP,tSaHead->sprtF->x+16,tSaHead->sprtF->y+16))
			   {startExplosion(tSaHead->sprtF->x+16,tSaHead->sprtF->y+16);
			    triggerSound(2);
			    tSaHead->exploding=1;
			    }
	 if(tSaHead->sprtF->x>300)
	    tSaHead=endSat(tSaHead);
	 else if(tSaHead->sprtF->x<0)
		tSaHead=endSat(tSaHead);
	      else tSaHead=tSaHead->next;
	}
    }
}

/**************************************/
struct nodeSprt *endSat(struct nodeSprt *sprtPtr)
{
struct nodeSprt *tNode;
if(sprtPtr==saHead)
    {saHead=sprtPtr->next;
     tNode=saHead;
     if(tNode)
	tNode->prev=NULL;
    }
else
    {tNode=sprtPtr->next;
     if(tNode)
	tNode->prev=sprtPtr->prev;
     sprtPtr->prev->next=tNode;
    }
FreeVec(sprtPtr->sprtF);
FreeSprite(sprtPtr->sprtNoF);
FreeVec(sprtPtr);
return tNode;
}
/**************************************/
void ignoreSat(struct nodeSprt *sprtPtr)
{
if(sprtPtr==saHead)
    saHead=NULL;
else
    sprtPtr->prev->next=NULL;
FreeVec(sprtPtr);
}

/**************************************/

struct nodeSprt *destroySat(struct nodeSprt *sprtPtr)
{
triggerSound(2);
startExplosion(sprtPtr->sprtF->x,sprtPtr->sprtF->y+10);
score+=sprtPtr->sprtF->y;
sprtPtr=endSat(sprtPtr);
return sprtPtr;
}
