/* -	ARTILLERY -	 */
#define xedvars 0

#include "stdio.h"
#include "types.h"
#include "math.h"
#include "intuition/intuition.h"
#include "intuition/screens.h"
#include "graphics/gfxbase.h"
#include "graphics/text.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "exec/memory.h"

#include "devices/timer.h"
struct timerequest tr;
struct MsgPort *tport;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct NewScreen gfxscn;
struct Screen *gfxscreen;
struct NewWindow frame;
struct Window *gfxwin;
struct IntuiMessage *gfxmsg;
struct RastPort *gfxrp;
struct MsgPort *xport;
struct IOStdReq *iport;
struct Device *ConsoleDevice;

struct InputEvent ievent = /*raw key input event*/
{
	NULL,					/*next event*/
	IECLASS_RAWKEY,	/*class*/
	0,0,0
};

int MaxStLen = 256;
#define MaxSt1 256  /*maxstlen */

int TOP = 1;
int BOT = 23;
int PW = 39;
int LLen;
int GX, GY;
ulong COLOR, BCOLOR;
int Tstyle;
char buff[10];
char func;
char Nstr[82],Path[258];
char *Msg;
int STAT = 2;

/* Define the size of the screen */
#define SC_HEIGHT 256
#define SC_WIDTH	320

#include "SCREEN.p";
#include "Artillery.p";

/* -	-	Menu	-	-	*/
/* back to front */
#define EDIT_MENU 0

#define EASY_ITEM 0
#define MED_ITEM 1
#define HARD_ITEM 2
#define HELP_ITEM 3
#define QUIT_ITEM 4

static struct IntuiText quit_text =
{
   15,8,JAM1,0,1,NULL,"Quit",NULL
};

struct MenuItem quit_item =
{
	NULL,
	0,40,75,10,
	ITEMTEXT |ITEMENABLED |HIGHCOMP,
	0,(APTR) &quit_text,
	NULL,0,NULL,MENUNULL
};

static struct IntuiText help_text =
{
   15,8,JAM1,0,1,NULL,"Help",NULL
};

struct MenuItem help_item =
{
	&quit_item,
	0,30,75,10,
	ITEMTEXT |ITEMENABLED |HIGHCOMP,
	0,(APTR) &help_text,
	NULL,0,NULL,MENUNULL
};

static struct IntuiText hard_text =
{
   15,8,JAM1,LOWCHECKWIDTH,1,NULL,"Hard",NULL
};

struct MenuItem hard_item =
{
	&help_item,
	0,20,75,10,
	ITEMTEXT |ITEMENABLED |CHECKIT |HIGHCOMP,
	0,(APTR) &hard_text,
	NULL,0,NULL,MENUNULL
};

static struct IntuiText med_text =
{
   15,8,JAM1,LOWCHECKWIDTH,1,NULL,"Medium",NULL
};

struct MenuItem med_item =
{
	&hard_item,
	0,10,75,10,
	ITEMTEXT |ITEMENABLED |CHECKIT |HIGHCOMP,
	0,(APTR) &med_text,
	NULL,0,NULL,MENUNULL
};

static struct IntuiText easy_text =
{
   15,8,JAM1,LOWCHECKWIDTH,1,NULL,"Easy",NULL
};

struct MenuItem easy_item =
{
	&med_item,
	0,0,75,10,
	ITEMTEXT |ITEMENABLED |CHECKIT |HIGHCOMP,
	0,(APTR) &easy_text,
	NULL,0,NULL,MENUNULL
};

struct Menu edit_menu =
{
	NULL,
	0,0,83,0,
	MENUENABLED,
   "Artillery",
	&easy_item
};
/* -	-	Menu	-	-	*/

short colours[16] =
{
	/* RGB */
	0x0000, 0x0DDD, 0x0a80, 0x0EE0, 0x0800, 0x0F00, 0x0808, 0x0E0E,
	0x0008, 0x000F, 0x0088, 0x00EE, 0x0071, 0x00e0, 0x0555, 0x0888
};
#define BLK 0
#define BRN 2
#define YLO 3
#define RED 5
#define BLU 9
#define CYAN 11
#define DGRN 12
#define GRN 13

BOOL OpenGFXScreen()
{
	gfxscn.LeftEdge = 0;
	gfxscn.TopEdge	 = 0;
	gfxscn.Width	 = SC_WIDTH;
	gfxscn.Height	 = SC_HEIGHT;
	gfxscn.Depth	 = 4;
	gfxscn.DetailPen= BRN;
	gfxscn.BlockPen = YLO;
	gfxscn.ViewModes= 0;
	gfxscn.Type		 = 0;
	gfxscn.Font		 = 0;
   gfxscn.DefaultTitle = "";
	gfxscn.Gadgets	 = 0;
	gfxscreen = (struct Screen *)OpenScreen(&gfxscn);
	return(BOOL)(gfxscreen != 0);
}

BOOL OpenGFXWindow()
{
	frame.LeftEdge = 0;
	frame.TopEdge	= 0;
	frame.Width		= SC_WIDTH;
	frame.Height	= SC_HEIGHT;
	frame.DetailPen= BRN;
	frame.BlockPen = YLO;
	frame.IDCMPFlags = MENUPICK| RAWKEY;
	frame.Flags		= BORDERLESS| SMART_REFRESH| ACTIVATE;
   frame.Title    = "Artillery";
	frame.Screen	= gfxscreen;
	frame.MinWidth = 0;
	frame.MaxWidth = -1;
	frame.MinHeight= 0;
	frame.MaxHeight= -1;
	frame.Type		= CUSTOMSCREEN;
	gfxwin = (struct Window *)OpenWindow(&frame);
	return(BOOL)(gfxwin != 0);
}

/* - -  - - */
#ifndef BRN
#define BRN 0
#define YLO 2
#define BLK 1
#define GRN 3
#endif
/*-------------------------*/
MenuCmd()
{
	int code,I,M = 27;
	code = gfxmsg->Code;
	if(code != MENUNULL)
	{
		switch(MENUNUM(code))
		{
			case EDIT_MENU:
			{
			I = ITEMNUM(code);
			if(I != NOITEM) M = (I + 1) * -8;
			}
			default: break;
		}
	}
	return(M);
}

char AsKey()
{
	int C = 0, len;
	if(gfxmsg->Code & IECODE_UP_PREFIX) {;}
	else
	{
		buff[0] = 0; buff[1] = 0; buff[2] = 0;
		ievent.ie_Code = gfxmsg->Code;
		ievent.ie_Qualifier = gfxmsg->Qualifier;
		ievent.ie_position.ie_addr = * (APTR *)gfxmsg->IAddress;
		len = RawKeyConvert(&ievent,buff,10,NULL);
		if(len > 0)
		{
			if(len == 1) { C = buff[0]; if(C == 0x7f) C = 7; }
			else										 /*DEL .. ^code*/
			{
				C = buff[1];
				if(buff[2] == '~') /* help & function keys */
				{
					func = '?';
					if((C >= '0') && (C <= '9')) func = C + 1;
					C = 31;
				}
				switch(C) /* arrow keys */
				{
				case 'A': C = 5;	break; /*^E ^*/
				case 'B': C = 24; break; /*^X v*/
				case 'C': C = 4;	break; /*^D >*/
				case 'D': C = 19; break; /*^S <*/
				case 'T': C = 18; break; /*^R ^^*/
				case 'S': C = 3;	break; /*^C vv*/
				case ' ':
				{
					if(buff[2] == 'A') C = 1; /*^A <<*/
					if(buff[2] == '@') C = 6; /*^F >>*/ break;
				}
				}
			}
		}
	}
	return(C);
}

char GetKey()
{
	int C = 0, class;
	do {
		if((gfxmsg = (struct IntuiMessage *)GetMsg(gfxwin->UserPort)) == 0L)
		{
			Wait(1 << gfxwin->UserPort->mp_SigBit); continue;
		}
		class = gfxmsg->Class;
		if(class == RAWKEY) C = AsKey(); /* convert arrow keys et al to char code */
		else if(class == MENUPICK) C = MenuCmd();
		ReplyMsg((struct Message *)gfxmsg);
	} while(C == 0);
	return(C);
}
/*-------------------------*/

SetAttr(S) /* Normal = 0 Uline = 1/2 Bold = 3/4 italic = 5/6 */
int S;
{
	ulong en;
	switch(S)
	{
	case 0: Tstyle = 0; break;
	case 1: Tstyle = Tstyle | 1; break;
	case 2: Tstyle = Tstyle & 6; break;
	case 3: Tstyle = Tstyle | 2; break;
	case 4: Tstyle = Tstyle & 5; break;
	case 5: Tstyle = Tstyle | 4; break;
	case 6: Tstyle = Tstyle & 3; break;
	}
	en = AskSoftStyle(gfxrp); SetSoftStyle(gfxrp,(ulong)Tstyle,en);
}

 /* 0 brn 1 ylo 2 bk 3 grn*/
SetCols() { SetAPen(gfxrp,COLOR); SetBPen(gfxrp,BCOLOR); }
YR() { COLOR = YLO; BCOLOR = BRN; SetCols(); SetAttr(0); }
KR() { COLOR = BLK; BCOLOR = BRN; SetCols(); SetAttr(0); }
KG() { COLOR = BLK; BCOLOR = GRN; SetCols(); SetAttr(0); }
GK() { COLOR = GRN; BCOLOR = BLK; SetCols(); SetAttr(0); }

int SetStLen(str)
char *str;
{
	char C; int E = 0, L = -1;
	do { ++L; C = str[L]; if((C == 0) || (C == 10) || (L >= MaxSt1)) E = 1; } while(E == 0);
	str[L] = 0;
	if(L >= MaxSt1)
	{
		E = 0; do { --L; C = str[L]; if((C > 32) || (L < 0)) E = 1; } while(E == 0);
		++L; str[L] = 0;
	}
	return(L);
}

WriteStr(str) char *str; { long L; Move(gfxrp,(long)GX,(long)GY); L = (long)SetStLen(str); Text(gfxrp,str,(ulong)L); GX +=(L << 3); }

WriteStN(str,L) char *str; int L; { Move(gfxrp,(long)GX,(long)GY); Text(gfxrp,str,(ulong)L); GX +=(L << 3); }

WriteCh(C) char C;/* due to the extra Moves it's faster to compose a str */

{
	Move(gfxrp,(long)GX,(long)GY); Nstr[0] = C;
	Text(gfxrp,Nstr,(ulong)1); GX += 8;
}

WriteCN(C,N) char C; int N; { int L; for(L = 0; L < N; L++) Nstr[L] = C; WriteStN(Nstr,N); }

WriteLong(W)
long W;
{
	int L = 79, S = 0;
	Nstr[L--] = 0;
	if(W < 0) { W = -W; S = 1; }
	do { Nstr[L--] = ((W % 10) + 48); W /= 10; } while((W > 0) && (L > 1));
	if(S == 1) Nstr[L--] = '-';
	WriteStr(&Nstr[(L + 1)]);
}
WriteInt(N) int N; { WriteLong((long)N); }

GotoY(L) int L; /*origin 1,1*/ { GX = 4; GY = (L << 3) + 10; /*if(GY == 18) GY = 17;*/ }
GotoXY(N,L) int N,L; { GX = (N << 3) - 4; GY = (L << 3) + 10; }

Cll(L) int L; { GotoY(L); WriteCN(' ',PW); GX = 4; }

char UPcase(C) char C; { if((C < 97) || (C > 122)) {;} else C -= 32; return(C); }

int StoI(str)
char *str;
{
	char C; int L, M = 0, N = -1;
	L = SetStLen(str);
	if((L > 0) && (str[0] != 10))
	{
		N = 0;
		do {
			C = str[M] - 48;
			if((C >= 0) && (C <= 9)) N = (N * 10) + C; else N = -1; ++M;
		}
		while((M < L) && (N != -1));
	}
	return(N);
}
/* - -  - - */

/* -	Real	-	*/
_getback() { if(LLen > 0) { WriteCh(' '); GX -= 16; --LLen; } else LLen = 0; }
GetStr() /* Path << kb ESC LLen*/
{
	char C;
	Path[0] = 0; LLen = 0;
	do {
		KG(); WriteCh(' '); GX -= 8; C = GetKey(); YR();
		if(C > 31)
		{
			if((C < 127) || (C > 159)) WriteCh(C); else WriteCh(169);
			Path[LLen] = C; ++LLen;
		}
		else
		{
			switch (C)
			{
			case	8:/* ^H */
			case 30:/* BS */ _getback(); break;
			case -40:
			case 27:/*ESC */ { C = 13; Path[0] = 10; LLen = 1; } break;
			case -32:
			case 31:/*help*/ Help(); break;
			default : break;
			}
		}
		if(LLen >= MaxSt1) { do { _getback(); } while(LLen >= MaxSt1); }
	}
	while(C != 13);
	Path[LLen] = 0;
}

double ReadReal()
{
	int F = 0, M, N, S = 0; double R = 0.0; char C;
	GetStr();
	if(Path[0] == 10) return(-1);
	else
	{
		if(Path[0] == '-') { Path[0] = '0'; S = 1; }
		M = -1; do { ++M; C = Path[M]; if((C == 0) || (C == '.')) F = 1; } while(F == 0);
		if(C == '.')
		{
			F = 0; N = M; do { ++N; C = Path[N]; if(C == 0) F = 1; } while(F == 0);
			N -= M;
			if(N > 1)
			{
				R = StoI(&Path[M + 1]);
				if(R != -1) { for(; N > 1; N--) R /= 10; } else R = 0;
			}
		}
		Path[M] = 0;
		R += StoI(Path); if(S == 1) R = -R;
	}
	return(R);
}

WriteReal(R,P) double R; int P; /* Num, Dec Pl */
{
	double D; long W; int N = 0;
	D = R;
	if(D < 0.0) { D = -D; WriteCh('-'); }
	W = (long)D; WriteLong(W); WriteCh('.');
	D -= (double)W;
	do { D *= 10; W = (long)D; Nstr[N++] = (W + 48); D -=(double)W; --P; } while(P > 0);
	Nstr[N] = 0; WriteStr(Nstr);
}

 ulong R_N_D; int R_N_;
unsigned RndInt(K) /* 0..K-1 */
unsigned K;
{
	ulong N;
	N = R_N_D; N++;
	R_N_++; if(R_N_ > 6) R_N_ = 0;
	switch (R_N_)
	{
		case	0: N *= 75; break;
		case	1: N *= 47; break;
		case	2: N *= 41; break;
		case	3: N *= 66; break;
		case	4: N *= 76; break;
		case	5: N *= 25; break;
		default: N *= 7; break;
	}
	R_N_D = N >> 1;
	return((N >> 2) % K);
}

Randomise()
{
	ulong micro;
	if(OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *) &tr,0) == 0L)
	{
		if((tport = (struct MsgPort *)CreatePort(0,0)) != 0)
		{
			tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
			tr.tr_node.io_Message.mn_Node.ln_Pri  = 0;
			tr.tr_node.io_Message.mn_Node.ln_Name = 0L;
			tr.tr_node.io_Message.mn_ReplyPort	  = tport;
			tr.tr_node.io_Command					  = TR_GETSYSTIME;
			DoIO((struct IORequest *) &tr);
			micro=tr.tr_time.tv_micro;
			DeletePort(tport);
		}
		CloseDevice((struct IORequest *) &tr);
	}
	R_N_D = micro; R_N_ = micro & 7;
}

/* -	ARTILLERY -	 */

#define WI 320
#define HI 200

 int Base[3],Score[3],Skill[3];
 int Hit,High,Play,Player,Wind;
 double Hite[322];
 double Try[4][3][3];
 double Angle;
 int Powder;
 BOOL Flash;

KC() { COLOR = BLK; BCOLOR = CYAN; SetCols(); SetAttr(0); }

Clgs()
{
	SetAPen(gfxrp,(ulong)CYAN);
	RectFill(gfxrp,0L,10L,(long)SC_WIDTH,200L);
	SetCols();
}

Clts()
{
	SetAPen(gfxrp,(ulong)BRN);
	RectFill(gfxrp,2L,203L,(long)SC_WIDTH-2,254L);
	SetCols();
}

Help()
{
	int ox,oy;
	ox = GX; oy = GY;
	KC();
   GotoXY(4, 4); WriteStr("To fire the cannon , you must..");
   GotoXY(4, 5); WriteStr("Enter bags of Powder up to about 30");
   GotoXY(4, 6); WriteStr("Then enter the Angle 10 to 170.0");
   GotoXY(4, 7); WriteStr("56.79 would be towards the enemy.");
   GotoXY(4, 8); WriteStr("Wind <-- --> affects shot flight.");
   GotoXY(4,10); WriteStr("First to 15 hits wins.");
	GX = ox; GY = oy;
}

Paws() { char C; GK(); GotoXY(15,30); WriteStr("Press a key"); C = GetKey(); Cll(30); }

IncPlayer() { ++Player; if(Player > 2) Player = 1; }

DCircle(x,y,r)
int x,y,r;
{
	int b,c,d,e; double a;
	c = (r * 51) >> 5; a = 1.57079 / (double)c;
	for(b=0; b <= c; b++)
	{
		d = (r * sin(b * a)); e = (r * cos(b * a));
		WritePixel(gfxrp,x+d,y+e);
		WritePixel(gfxrp,x+d,y-e);
		WritePixel(gfxrp,x-d,y+e);
		WritePixel(gfxrp,x-d,y-e);
	}
}

DrawTer()
{
	int A,B,C,T,X,Y;
	Clgs();
	for(X=0; X <= WI; X++) /* DRAW LAND */
	{
		Move(gfxrp,X,200); Y = (int)Hite[X];
		SetAPen(gfxrp,(ulong)GRN); Draw(gfxrp,X,200 - (Y / 2));
		SetAPen(gfxrp,(ulong)DGRN); Draw(gfxrp,X,200 - Y);
	}

	KC(); GotoXY(15,1);
   if(Wind > 0) { WriteStr(">>--> "); WriteInt(Wind); }
   else { WriteInt( -Wind); WriteStr(" <--<<"); }

	for(T=-1; T < 2; T++) /* DRAW CANNON */
	{
		if(T != 0)
		{
			KC();
         if(T == 1) X = 32; else X = 1; GotoXY(X,1); WriteStr("Score:");
			if(T == 1) Y = 1; else Y = 2;
			WriteInt(Score[Y]); X = Base[Y]; Y = HI - (int)Hite[X] + 1;

			/* DRAW CANNON /o o\ */
			A = T * 6; B = X + A; C = X - A; A = Y + 1;
			Move(gfxrp,B-T,A); Draw(gfxrp,X-T,Y-5);
			Move(gfxrp,B,A); Draw(gfxrp,C,Y-11);
			Move(gfxrp,B,Y); Draw(gfxrp,C,Y-12);
			Move(gfxrp,B,Y-1); Draw(gfxrp,X+T,Y-6);

			DCircle(X,Y,5); /* DRAW WHEEL */
			SetAPen(gfxrp,(ulong)BRN); DCircle(X,Y,4);
			SetAPen(gfxrp,(ulong)RED); DCircle(X,Y,2);
		}
	}
}

GenTer()
{
	int M,N,T,U,YP,Low; int TER[12],TEMP[12];
	double Y;
	for(N=0; N < 12; N++) TEMP[N] = RndInt(40); /* 0 ^v^vv^ 10 */
	for(N=0; N < 11; N++) TER[N] = TEMP[N] + TEMP[N + 1]; /* less spikey */
	Low = HI; High = 0;
	for(M=0; M < 10; M++) {
		T = TER[M]; U = TER[M + 1];
		for(N=0; N < 32; N++) { /* ten points to 320 */
			Y = (T * (32 - N) + (U * N)) / 32;
			Hite[(M * 32) + N] = Y;
			YP = (int)Y;
			if(YP > High) High = YP; if(YP < Low) Low = YP;
		}
	}
	U = 20 - Low;
	for(N=0; N <= WI; N++) Hite[N] += U; /* lowest = 20 ^v^vv^*/
	High += U;
	Wind = RndInt(61) - 30; /* +-30 */
	Base[2] = 6 + RndInt(100); Base[1] = 214 + RndInt(100);
	DrawTer();
}

Fire()
{
	int A,C,E,N,T,XP,YP,Skil,Posn;
	double X,Y,Hv,HvW,Vv,PX,AX;

	AX = PI * (Angle / 180);
	PX = (double)(Powder * Powder) / 300; /*1.3..3*/
	Vv = PX * sin(AX);
	Hv = PX * cos(AX); if(Player == 2) Hv = -Hv; /* P2 P1 */
	Posn = Base[Player];									/* -1 1	*/
	X = Posn;
	Y = Hite[Posn] + 5;
	if((Powder < 8) || (Powder > (32 + RndInt(10)) ) || (Angle < 10) || (Angle > 170)) T = -1; /* SELF DESTRUCT */
	else
	{
		SetAPen(gfxrp,(ulong)BRN);
		HvW = Hv; E = 0;
		do {
			if(Y > High) HvW = Hv - ((double)Wind / 70);
			X = X - HvW; Y = Y + Vv; /* + then - */
			Vv = Vv - 0.0322; /* GRAVITY */
			XP = (int)X; YP = HI - (int)Y;
			if(E < 6) E++;
			else {
				WritePixel(gfxrp,XP,YP);
				if(( Hite[XP] > Y) || (XP <= 0) || (XP >= WI)) E = -1;
			}
		}	while(E != -1);
	  T = 1;
	}
	if((T == -1) || ((XP > (Posn - 5)) && (XP < (Posn + 5)))) T = -1;
	else
	{
		IncPlayer(); Posn = Base[Player]; IncPlayer(); /*get target*/
		Skil = Skill[Player] / 3;
	}

	if((T == -1) || ((XP >= Posn - Skil) && (XP <= Posn + Skil)))
	{ /* self-destruct, or Hit*/
		if(T == -1) IncPlayer();
		A = Score[Player]; ++A; Score[Player] = A;
		if(T == -1) IncPlayer();
		if(Skil < 3) Flash = FALSE;
		if(A > 14) STAT = 1;
		/*--Skill[Player];*/
		Hit = 1;
		YP = HI - (int)Hite[Posn]; SetAPen(gfxrp,(ulong)RED);
		if(Flash) {
			for(N=1; N < 6; N++)
			{
				A = 30 - (N * 5);
				XP = Posn - A; C = Posn + A;
				A = YP - (N * 5);
				Move(gfxrp,Posn,YP); Draw(gfxrp,XP,A);
				Move(gfxrp,Posn,YP); Draw(gfxrp,C,A);
				E = YP - 1;
				Move(gfxrp,Posn,E); Draw(gfxrp,XP,A);
				Move(gfxrp,Posn,E); Draw(gfxrp,C,A);
			}
		} else {
			Move(gfxrp,Posn,YP); Draw(gfxrp,Posn,YP-8);
			Move(gfxrp,Posn-8,YP); Draw(gfxrp,Posn+8,YP);
		}
		if(T == -1) IncPlayer();
		if(Player == 1) T = 32; else T = 1;
      KC(); GotoXY(T,1); WriteStr("Score:");
		WriteInt(Score[Player]);
		if(T == -1) IncPlayer();
		Paws();
	}
}

Tries()
{
	int L,P,X; double R;
	if(Player == 1) X = 28; else X = 1; KG();
   GotoXY(X,26); WriteStr("Powder Angle"); YR();
	for(L=1; L < 4; L++)
	{
		GotoXY(X,(L + 26));
		P = (int)Try[L][1][Player]; R = Try[L][2][Player];
      if(P > 0) WriteInt(P); else WriteStr("--"); WriteStr("     ");
      if(R > 0) WriteReal(R,2); else WriteStr("--.--");
	}
	Cll(30);
}

GetShot()
{
	int X,Y,E;

	do {
		Tries(); E = 1;
		if(Player == 1) X = 21; else X = 1;
      KR(); GotoXY(X,30); WriteStr("Powder ?     0..~30");
		if(Player == 1) X = 28; else X = 8;
		GotoXY(X,30); Powder = (int)ReadReal();
		if(((Powder > 1) && (Powder < 40)) || (Powder == -1)) E = 0;
		if(Powder == -1) STAT = 1;
	}	while(E == 1);
	if(STAT > 1)
	{
		for(X=1; X < 3; X++) { /* MOVE OLD VALUES 1=2 2=3*/
			for(Y=1; Y < 3; Y++) Try[X][Y][Player] = Try[X + 1][Y][Player];
		}
		Try[3][1][Player] = (double)Powder; Try[3][2][Player] = 0;
		do {
			Tries(); E = 1;
			if(Player == 1) X = 22; else X = 1;
         KR(); GotoXY(X,30); WriteStr("Angle ?      0-180");
			if(Player == 1) X = 28; else X = 7;
			GotoXY(X,30); Angle = ReadReal();
			if(((Angle > 0) && (Angle < 180)) || (Angle == -1)) E = 0;
			if(Angle == -1) STAT = 1;						/* Esc */
		}	while(E == 1);
		if(Angle > -1) { Try[3][2][Player] = Angle; Tries(); }
	}
}

Game()
{
	int Shot,X; char Ch;
	OffMenu(gfxwin,0);
	OffMenu(gfxwin,1 << 5);
	OffMenu(gfxwin,2 << 5);
	Clts();
	Player = RndInt(2); if(Player == 0) Player = 2;
	Score[1] = Score[2] = 0;
	Flash = TRUE; STAT = 2;
	do {
		Shot = 0; Hit = 0;
		for(X=1; X < 4; X++) {
			Try[X][1][1] = Try[X][1][2] = Try[X][2][1] = Try[X][2][2] = 0;
		}
		GenTer();
		do {
			GetShot();
			if(STAT > 1)
			{
				Fire();
				IncPlayer();
				++Shot;
				if(((Shot % 8) == 0) && (Hit < 1)) { Paws(); DrawTer(); Tries(); }
			} else {
            Clts(); YR(); GotoXY(1,27); WriteStr("Do you want to quit ?");
				GetStr(); Ch = UPcase(Path[0]);
				if((Ch == 'Q') || (Ch == 'Y')) { STAT = 0; Hit = 1; }
				else { Cll(27); DrawTer(); Tries(); STAT = 2; }
			}
		}	while(Hit == 0);
		Clts();
	}	while(STAT == 2);
	if((Score[1] == 15) || (Score[2] == 15))
	{
		if(Score[1] == 15) X = 29; else X = 1;
      YR(); GotoXY(X,27); WriteStr("Gosh well done !");
	}
	OnMenu(gfxwin,0);
	OnMenu(gfxwin,1 << 5);
	OnMenu(gfxwin,2 << 5);
}
/* -	ARTILLERY -	 */

Start()
{
	int C;
	SetAPen(gfxrp,(ulong)YLO); RectFill(gfxrp,0L,201L,(long)SC_WIDTH,256L);
	YR(); Clts();
   GotoXY(1,25); WriteStr("Loading Libs:Mathieeedoubbas.library");
   GotoXY(1,26); WriteStr("Loading Libs:Mathieeedoubtrans.library");
	Randomise();
	do {
		GenTer();
		Clts(); Skill[1] = 0;
		C = GetKey();
		switch (C) /* MenuCmnds */
		{
			case -8: Skill[1] = 15; break;
			case -16: Skill[1] = 9; break;
			case -24: Skill[1] = 3; break;
			case	31:
			case -32: Help(); break;
			case	10:
			case -40: STAT = 0; break;
		}
		if(Skill[1] > 0) { Skill[2] = Skill[1]; Game(); }
	}	while(STAT);
}

main(argc,argv)
int argc;
char *argv[];
{
	long d;
   if((IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) != 0)
	{
      if((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)) != 0)
		{
			if(OpenGFXScreen())
			{
				LoadRGB4(&gfxscreen->ViewPort,colours,16L); /* Set the colours */
				if(OpenGFXWindow())
				{
					SetMenuStrip(gfxwin, &edit_menu); /* Set up the menu strip */
					gfxrp = gfxwin->RPort;
               if((xport = (struct MsgPort *)CreatePort("conread",0)) != 0L)
					{
						if((iport = (struct IOStdReq *)CreateStdIO(xport)) != 0L)
						{
                     if((d = OpenDevice("console.device",-1,iport,0)) == 0)
							{
								ConsoleDevice = iport->io_Device;

								Start();

								if((d = CheckIO(iport)) == FALSE) AbortIO(iport);
							}
							DeleteStdIO(iport);
						}
						DeletePort(xport);
					}
					ClearMenuStrip(gfxwin);
					CloseWindow(gfxwin);
				}
				CloseScreen(gfxscreen);
			}
		}
	}
}
/* -	ARTILLERY -	 */

