;/*
sc RESOPT IGNORE=73 DATA=NEAR NMINC UCHAR CONSTLIB STREQ STRMERGE NOSTKCHK NOSTDIO OPTIMIZE OPTSIZE TicTacToe.c
slink from LIB:c.o TicTacToe.o to //Clients/TicTacToe LIB LIB:sc.lib LIB:amiga.lib /lib/client.lib SC SD NOICONS STRIPDEBUG
delete TicTacToe.o
quit

 TicTacToe 1.0  (Client for BServer)

 (Played between two blind persons who don't know the rules and can't
  remember even a single cell... ;-)

 Copyright © 1994-1995 by Stefano Reksten of 3AM - The Three Amigos!!!
 All rights reserved.
*/

#include <exec/types.h>
#include <intuition/intuition.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <clib/alib_protos.h>

#include "/include/client.h"

char *ver = "$VER: TicTacToe 1.0 "__AMIGADATE__;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DisplayIDInformation *dinfo;
struct Screen *scr;

UBYTE matrix[9];
UWORD  swidth, sheight;

extern ULONG RangeSeed;

#define IDLE_0LN 1
#define IDLE_1LN 2
#define IDLE_2LN 3
#define IDLE_3LN 4
#define IDLE_4LN 5
#define MOVEX	 6
#define MOVEY	 7
#define ENDED    8


void InitMatrix( void )
{
register int n;
for ( n = 0; n < 9; n++ )
	matrix[n] = 0;
SetRast( &scr->RastPort, 0 );
}


void ChalkLine( UBYTE color, UWORD fromx, UWORD fromy, UWORD tox, UWORD toy )
{
register struct RastPort *rp = &scr->RastPort;
SetAPen( rp, color );
Move( rp, fromx + RangeRand( 19 ) - 9, fromy + RangeRand( 19 ) - 9 );
Draw( rp, tox + RangeRand( 19 ) - 9, toy + RangeRand( 19 ) - 9 );
}


BOOL SomeoneWins( void )
{
register int n;
for ( n = 0; n < 3; n++ )
	{
	if ( matrix[3*n] && matrix[3*n] == matrix[3*n+1] && matrix[3*n] == matrix[3*n+2] )
		{
		ChalkLine( matrix[3*n], 20, (1+(n<<1))*sheight/6, swidth - 20, (1+(n<<1))*sheight/6 );
		return TRUE;
		}
	if ( matrix[n] && matrix[n] == matrix[3+n] && matrix[3+n] == matrix[6+n] )
		{
		ChalkLine( matrix[n], (1+(n<<1))*swidth/6, 20, (1+(n<<1))*swidth/6, sheight - 20 );
		return TRUE;
		}
	}
if ( matrix[0] && matrix[0] == matrix[4] && matrix[4] == matrix[8] )
	{
	ChalkLine( matrix[0], 20, 20, swidth - 20, sheight - 20 );
	return TRUE;
	}
if ( matrix[2] && matrix[2] == matrix[4] && matrix[4] == matrix[6] )
	{
	ChalkLine( matrix[2], swidth - 20, 20, 20, sheight - 20 );
	return TRUE;
	}
return FALSE;
}


void PutASign( int player )
{
int move;

do {
	move = RangeRand( 9 );
	} while( matrix[move] );

matrix[move] = player - MOVEX + 1;

if ( player == MOVEX )
	{
	UWORD x, y;
	x = (swidth/3) * ( move % 3 ) + 20;
	y = (sheight/3) * ( move / 3 ) + 20;
	ChalkLine( 2, x, y, x + swidth/3 - 40, y + sheight/3 - 40 );
	ChalkLine( 2, x + swidth/3 - 40, y, x, y + sheight/3 - 40 );
	}
else
	{
	SetAPen( &scr->RastPort, 3 );
	DrawEllipse( &scr->RastPort, (1+2*(move%3))*swidth/6, (1+2*(move/3))*sheight/6, swidth/6 - 20 - RangeRand( 10 ), sheight/6 - 20 - RangeRand( 10 ) );
	}
}


BOOL MatrixFull( void )
{
register int n;
for ( n = 0; n < 9; n++ )
	if ( !matrix[n] )
		return FALSE;
return TRUE;
}


void Blank( void )
{
struct Rectangle *rect;
UBYTE brightness;

int status, ticks = 9, counter = 0;

rect = GETTXTOSCANRECT(dinfo);

swidth = RECTANGLEWIDTH(rect);
sheight = RECTANGLEHEIGHT(rect);
brightness = GETBRIGHTNESS(dinfo);

if ( scr = OpenScreenTags( NULL,
	SA_DisplayID, DISPLAYID( dinfo ),
	SA_Width, swidth,
	SA_Height, sheight,
	SA_Depth, 2,
	TAG_END ) )
	{
	register struct ViewPort *vp = &(scr->ViewPort);

	SpritesOff();

	SetRGB4( vp, 0, 0, 0, 0 );
	SetRGB4( vp, 1, 15*brightness/100, 15*brightness/100, 15*brightness/100 );
	SetRGB4( vp, 1, 10*brightness/100, 0, 0 );
	SetRGB4( vp, 1, 0, 10*brightness/100, 0 );

	InitMatrix();
	status = IDLE_0LN;

	while( STILL_BLANKING )
		{
		WaitTOF();

		if ( ++ticks == 15 )
			{
			ticks = 0;
			if ( status == IDLE_0LN )
				{
				ChalkLine( 1, swidth/3, 20, swidth/3, sheight - 20 );
				status = IDLE_1LN;
				}
			else
			if ( status == IDLE_1LN )
				{
				ChalkLine( 1, 2*swidth/3, 20, 2*swidth/3, sheight - 20 );
				status = IDLE_2LN;
				}
			else
			if ( status == IDLE_2LN )
				{
				ChalkLine( 1, 20, sheight/3, swidth - 20, sheight/3 );
				status = IDLE_3LN;
				}
			else
			if ( status == IDLE_3LN )
				{
				ChalkLine( 1, 20, 2*sheight/3, swidth - 20, 2*sheight/3 );
				status = IDLE_4LN;
				}
			else
			if ( status == IDLE_4LN )
				status = MOVEX + RangeRand( 2 );
			else
			if ( status == MOVEX || status == MOVEY )
				{
				if ( MatrixFull() )
					status = ENDED;
				else
					{
					PutASign( status );
					if ( SomeoneWins() )
						status = ENDED;
					}
				if ( status != ENDED )
					status = status == MOVEX ? MOVEY : MOVEX;
				}
			else
				{
				if ( ++counter == 10 )
					{
					InitMatrix();
					status = IDLE_0LN;
					counter = 0;
					}
				}
			}
		}

	CloseScreen( scr );
	SpritesOn();
	}
else
	SendClientMsg( ACTION_FAILED );
}


void __main( char *line )
{
if ( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37L ) )
	{
	if ( GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 37L ) )
		{
		if ( dinfo = OpenCommunication() )
			{
			CurrentTime( &RangeSeed, &RangeSeed );
			Blank();
			CloseCommunication( dinfo );
			}
		CloseLibrary( (struct Library *)GfxBase );
		}
	CloseLibrary( (struct Library *)IntuitionBase );
	}
}
