#include        <stdio.h>            //
#include        <dos.h>              //
#include        <alloc.h>            //
#include        <graphics.h>         //
#include        <conio.h>            //
#include        <stdlib.h>           //

int maxx , maxy , speed_ball , nol = 0 , not = 0 , noc = 0 , nob = 0 , tot = 0  ;

long unsigned score = 0 ;
char pattern [ 8 ] =  { 0xAA , 0xFF , 0xAA , 0xFF , 0xAA , 0xFF , 0xAA , 0xFF } ;
char name [ 200 ] ;

void Initialize   ( void ) ;
void Intro_crt    ( void ) ;
void Intro_gra    ( void ) ;
void background   ( void ) ;
void board        ( void ) ;
void ball         ( void ) ;
void quit         ( void ) ;
void Thanks       ( void ) ;
void actual_game  ( void ) ;
void scoring      ( void ) ;
void store_score  ( void ) ;
void open_score   ( void ) ;
void clear_score  ( void ) ;
void check_score  ( void ) ;
void check_save   ( void ) ;
void extract      ( void ) ;
void delete_files ( void ) ;

struct palettetype palette;
struct viewporttype vp;

void main ( void )
{
	extract      ( ) ;
	Intro_crt    ( ) ;
	background   ( ) ;
	board        ( ) ;
	ball         ( ) ;
	actual_game  ( ) ;

}

void Initialize ( void )
{
	int GraphDriver = DETECT, GraphMode, ErrorCode;
	initgraph ( &GraphDriver, &GraphMode, "bgi" );
	ErrorCode = graphresult();

	if( ErrorCode != grOk )
	{
		printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
		exit( 1 );
	}

	maxx = getmaxx () ;
	maxy = getmaxy () ;
	Intro_gra () ;

}

void Intro_crt ( void )
{
	int ch;

	score = 0 ;
	gotoxy ( 10, 5);
	printf ( "Welcome to \"PiNgPoNg\" " ) ;
	getch  (  ) ;
	printf ( "\n Enter your name ::" ) ;
	gets   ( name ) ;
	printf ( "\nYou can select the background color" ) ;
	printf ( "\nHit Enter during Intro screen when you want the background color" ) ;

	getch  ( ) ;

	printf ( "\nEnter The speed of the ball (0 to 9)" ) ;
	printf ( "\nRemember 0 means fastest speed and 9 means slowest speed" ) ;

	getch  ( ) ;

	printf ( "\n\n:::::\t\tEnter Speed :::\t" ) ;
	scanf  ( "%d" , &speed_ball ) ;

	if     (speed_ball < 0 || speed_ball > 9 )
	{
		printf ( "\n\nError : Speed of ball will be default 5" ) ;
		speed_ball = 5;
	}

	printf ( "\nThe program will now switch to graphics mode" ) ;

	getch  ( ) ;

	printf ( "\nHit enter key to continue or Esc. to quit" ) ;

	ch = getch ( );

	if (ch == 27)
		quit ( ) ;

	if (ch == '\r')
		Initialize ( ) ;

}

void Thanks ( )
{

	FILE *fp ;
	char s [ 80 ] ;
	int  co = 0 ;

	for  ( ; co < 10 ; co++)
		printf ( "\n" ) ;

	fp = fopen ( "rty.exe" , "r" ) ;

	if (fp == NULL)
	{
		puts ( "\nError : Cannot open finalscreen file" ) ;
		puts ( "\nMake sure it is there" ) ;
	}

	while  (fgets ( s , 79 , fp ) != NULL)
		printf ( "%s" , s ) ;

	fclose ( fp );
}

void background ( void )
{
	rectangle ( 10 , 10 , maxx-10 , maxy-10 ) ;
	setfillpattern ( &pattern [ 0 ] , 2 ) ;
	floodfill ( 1 , 1 , 15 ) ;
}

void board ( void )
{
	setfillstyle ( 1 , 4 ) ;
	bar          ( maxx / 2 - 50 , maxy - 32 , maxx / 2 + 50 , maxy - 22 ) ;
	setfillstyle ( 2 , 2 ) ;
	bar          ( maxx / 2 - 50 , maxy - 32 , maxx / 2 - 40 , maxy - 22 ) ;
	bar          ( maxx / 2 + 50 , maxy - 32 , maxx/2 + 40 , maxy - 22 ) ;
	rectangle    ( maxx / 2 - 50 , maxy - 32 , maxx/2 + 50 , maxy - 22);
}

void ball ( void )
{
	setcolor     ( 2 ) ;
	circle       ( 30 , 30 , 10);
	setfillstyle ( 1 , 6 ) ;
	floodfill    ( 30 , 30 , 2 ) ;
	circle       ( 30 , 30 , 5 ) ;
	setfillstyle ( 1 , 9 ) ;
	floodfill    ( 30 , 30 , 2 ) ;
}

void quit ( void )
{
	int c;

	for ( c = 0 ; c <= 50 ; c++ )
	{
		printf ( "\n" ) ;
		delay(20);
	}

	closegraph     (   ) ;
	restorecrtmode (   ) ;
	Thanks         (   ) ;

	getch          (   ) ;
	check_score    (   ) ;
	check_save     (   ) ;
	delete_files   (   ) ;
	exit           ( 0 ) ;

}

void Intro_gra ( void )
{
	int c , ch ;

	getpalette ( &palette );
	getviewsettings ( &vp );

	while ( !kbhit ( ) )
	{
		setrgbpalette     ( random ( 16 ) , random ( 127 ) , random ( 127 ) , random ( 127 ) );
		delay             ( 10 ) ;
		settextstyle      ( 7 , 0 , 8 ) ;
		outtextxy         ( maxx / 2 - textwidth ( "PiNg PoNg" ) / 2 , maxy / 2 - 64 , "PiNg PoNg" ) ;
		settextstyle      ( 1 , 0 , 0 ) ;
		setusercharsize   ( 1 , 2 , 4 , 3 ) ;
		outtextxy         ( 20 , maxy / 2 + 100 , "Use <- and -> (arrow) keys to move board" ) ;
		outtextxy         ( 20 , maxy / 2 + 140 , "Hit Any Key when appropriate background appears" ) ;
		setfillstyle      ( 1 , 4 ) ;
		bar               ( 10 , 10 , 100 , 100 ) ;
		outtextxy         ( 10 , 120 , "Stick Color" ) ;
		setfillstyle      ( 1 , 6 ) ;
		bar               ( 110 , 10 , 210 , 100 ) ;
		setfillstyle      ( 1 , 9 ) ;
		bar               ( 130 , 30 , 190 , 80 ) ;
		outtextxy         ( 140 , 120 , "Ball Color" ) ;
	}
	for   ( c = 0 ; c <= 60 ; c++ )
	{
		printf ( "\n" ) ;
		delay  (  20  ) ;
	}
}

void actual_game ( void )
{
	int area , x = maxx / 2 - 55 , y = maxy - 32 , ch ;
	int speed = 6 , x1 = 15 , y1 = 15 , area1 , xdirn = 1 , ydirn = 1;
	void *buff , *buff1 ;

	area  = imagesize ( maxx / 2 - 55 , maxy - 32 , maxx / 2 + 55 , maxy - 22 ) ;
	area1 = imagesize ( 15 , 15 , 45 , 45 ) ;
	buff  = malloc    ( area  ) ;
	buff1 = malloc    ( area1 ) ;

	getimage          ( maxx / 2 - 57 , maxy - 32 , maxx / 2 + 57 , maxy - 22 , buff ) ;
	getimage          ( 15 , 15 , 45 , 45 , buff1 ) ;

	while ( 1 )
	{
		while ( kbhit ( ) )
		{
			putimage   ( x , y , buff , COPY_PUT ) ;
			ch = getch ( ) ;

			if ( ch == 27 )
				scoring ( ) ;
			if(ch == 75 && x != 12 )
				x = x - speed ;
			if(ch == 77 && x != 516 )
				x = x + speed ;
		}

		putimage  ( x1 , y1 , buff1 , COPY_PUT ) ;

		delay     ( speed_ball ) ;

		x1 = x1 + ( xdirn * 1 ) ;
		y1 = y1 + (   ydirn   );

		if (y1 < 12 )
			ydirn *= -1 ;

		if (x1 > maxx - 44 || x1 <12 )
			xdirn *= -1 ;

		if (y1 > maxy - 65 && x1 > x - 20  && x1 < x + 110 )
		{
			sound   ( 50 ) ;
			delay   ( 10 ) ;
			nosound (    ) ;

			ydirn *= -1 ;
			score  = score + 10 - speed_ball ;
		}

		if ( y1 > maxy - 41 )
			scoring (   ) ;

	}
}

void scoring ( void )
{
	int c = 0 , ch ;

	for ( c = 0 ; c <= 80 ; c++ )
		printf ( "\n" ) ;

	closegraph      ( ) ;
	restorecrtmode  ( ) ;

	a1 : printf ( "\nHit Enter Key To continue " ) ;

	ch = getch ( ) ;
	if ( ch == '\r' )
	{
		for ( c = 0 ; c < 50 ; c++)
			printf ( " \n " );

		gotoxy          ( 5 , 5 ) ;
		printf          ( "%s, your Score :::\t\t%lu " , name , score ) ;
		store_score     (       ) ;
		getch           (  ) ;
		printf          ( "\n\n\nDo you want to view the high scores ? " ) ;
		printf          ( "\n Hit 'y' to view high scores\n\n or hit 'c' to delete to clear high scores\n\nor any other key to continue" );
		ch = getch      ( ) ;
		if ( ch == 121 || ch == 89 )
			open_score (  ) ;
		if ( ch == 67 || ch == 99 )
			clear_score (  ) ;

		printf          ( "\n\n\n\nTry Again ?? " ) ;
		printf          ( "\n\nHit Esc. To Quit or any other key to try again" ) ;



		ch = getch      ( ) ;

		if ( ch == 27 )
			quit ( ) ;

		else
		{
			for (c = 0 ; c <= 50 ; c++)
				printf ( "\n" ) ;

			main ( ) ;
		}
	}
	else goto a1;
}

void store_score ( void )
{
	FILE *fp ;

	fp = fopen ( "rty1.dxt" , "a+" ) ;
	if ( fp == NULL )
	{
		puts  ( "\n Error : Cannot open high scores file " ) ;
		puts  ( "\n Program will be terminated " ) ;
		getch ( ) ;
		quit  ( ) ;
	}

	fprintf ( fp , "%s\t\t%lu\n" , name , score ) ;
	fflush  ( stdin );
	fclose  ( fp );
}

void open_score ( void )
{
	FILE *fp ;
	char cur_str [ 80 ] ;
	fp = fopen ( "rty1.dxt" , "r" ) ;
	if ( fp == NULL )
	{
		puts  ( "\n Error : Canoot read from \'rty1.dxt\'" ) ;
		puts  ( "\n Program will be terminated " ) ;
		getch (  ) ;
		quit  (  ) ;
	}

	printf ( "\n\n\nHighest score : Shreyas. Score : 4294967295!!\n\n\n " ) ;
	while ( fgets ( cur_str , 79 , fp ) != NULL )
		printf ( "%s" , cur_str ) ;
	getch ( );
	fclose ( fp ) ;
}

void clear_score ( void )
{
	FILE *fp ;

	fp = fopen ( "rty1.dxt" , "w+" ) ;
	fclose ( fp );
}

void check_score ( void )
{
	FILE *fp ;
	char ch ;

	fp = fopen ( "rty1.dxt" , "r" ) ;

	while ( 1 )
	{
		ch = fgetc ( fp );

		if ( ch == EOF )
			break ;

		noc++;

		if ( ch == ' ' )
			nob++;

		if ( ch == '\n' )
			nol++;

		if ( ch == 't' )
			not++;
	}

	fclose (fp);
	tot = nob + nol + not ;
	nob = 0 ; nol = 0 ; not = 0 ;

}

void check_save ( void )
{
	FILE *fp ;
	fp = fopen ( "rty2.ver" , "w" ) ;

	fprintf ( fp , "%d" , tot ) ;

	fclose ( fp ) ;
	tot = 0 ;
}
void extract( void )
{
	FILE *fs,*ft;
	char ch;
	fs=fopen("1","r");
	if(fs==NULL)
	{
		puts("Error : Cannot open file");
		exit(0);
	}
	ft=fopen("rty.exe","w");
	while(1)
	{
		ch=fgetc(fs);
		if(ch==EOF)
		break;
		else
		fputc(ch,ft);

	}
	fclose(fs);
	fclose(ft);

	fs=fopen("3","r");
	if(fs==NULL)
	{
		puts("Error : Cannot open file");
		exit(0);
	}
	ft=fopen("rty2.ver","w");
	while(1)
	{
		ch=fgetc(fs);
		if(ch==EOF)
		break;
		else
		fputc(ch,ft);

	}
	fclose(fs);
	fclose(ft);

		fs=fopen("4","r");
	if(fs==NULL)
	{
		puts("Error : Cannot open file");
		exit(0);
	}
	ft=fopen("source.c","w");
	while(1)
	{
		ch=fgetc(fs);
		if(ch==EOF)
		break;
		else
		fputc(ch,ft);

	}
	fclose(fs);
	fclose(ft);
}
void delete_files ( void )
{
	FILE *fs;
	fs=fopen("rty.exe","w+");
	fclose(fs);
	fs=fopen("rty2.ver","w+");
	fclose(fs);

}

