	/*
 * Userspace program that communicates with the led_vga device driver
 * primarily through ioctls
 *
 * Stephen A. Edwards
 * Columbia University
 */

#include <stdlib.h>
#include <stdio.h>
#include "vga_led.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "usbkeyboard.h"
struct libusb_device_handle *keyboard;
uint8_t endpoint_address;
int vga_led_fd;

/* Read and print the segment values */
void print_segment_info() {
  vga_led_arg_t vla;
  int i;

  for (i = 0 ; i < VGA_LED_DIGITS ; i++) {
    vla.digit = i;
    if (ioctl(vga_led_fd, VGA_LED_READ_DIGIT, &vla)) {
      perror("ioctl(VGA_LED_READ_DIGIT) failed");
      return;
    }
    printf("%02x ", vla.segments);
  }
  printf("\n");
}

/* Write the contents of the array to the display */
void write_segments(const int segs[38])
{
  vga_led_arg_t vla;
  int i;
  for (i = 0 ; i < VGA_LED_DIGITS ; i++) {
    vla.digit = i;
    vla.segments = segs[i];
    if (ioctl(vga_led_fd, VGA_LED_WRITE_DIGIT, &vla)) {
      perror("ioctl(VGA_LED_WRITE_DIGIT) failed");
      return;
    }
  }
}

int main()
{
    struct usb_keyboard_packet packet;
  	int transferred;
    char keystate[12];
    if ( (keyboard = openkeyboard(&endpoint_address)) == NULL )
    {
        fprintf(stderr, "Did not find a keyboard\n");
        exit(1);
  	}

    //int left,leftup,up,leftdown,down,rightdown,right,rightup;
  	//int clear_key = 1;



    vga_led_arg_t vla;
    //printf("01\n");
    static const char filename[] = "/dev/vga_led";// the driver.c
    //printf("02\n");
    //initial position of every enemy and its flag,
    static int xyf[38] = {
			300, 200, 1,	//chara x0-0 y0-1 f0-2 
			500,200,0,	//bullet1 x1-3 y1-4 f1-5
			500,300,0,		//bullet2 x2-6 y2-7 f2-8
			500,400,0,	//bullet3 x3-9 y3-10 f3-11
			500,300,0,1,	//enemy1 x4-12 y4-13 f4-14 id4-15
			100,300,0,2,	//enemy2 x5-16 y5-17 f5-18 id5-19
			400,300,0,2,	//enemy3 x6-20 y6-21 f6-22 id6-23
			0,		//floor	x7-24
			0,		//brick x8-25
			100,400,0,		//explosion1 x9-26 y9-27 f9-28
			300,400,0,		//explosion2 x10-29 y10-30 f10-31 
			500,400,0,		//exlposion3 x11-32 y11-33 f11-34
			300,100,0		//airflow x12-35 y12-36 f12-37
			};	
    printf("VGA axis Userspace program started\n");

    if ( (vga_led_fd = open(filename, O_RDWR)) == -1)
    {
        fprintf(stderr, "could not open %s\n", filename);
        return -1;
    }

    printf("initial state: ");
    print_segment_info();
    //write the initial value to the register
    write_segments(xyf);
    printf("fuck you \n");

    printf("current state: ");
    print_segment_info();
  
    int xmove, ymove;
    int t1=0;   //t used in calculate the y speed of chara
    int t2=0;
    //int v1=0;
    //int v2=0;
    //int v=0;
    int updown=0;
    int bulletx[3]={0,0,0};
    int bullety[3]={0,0,0};
    int enemyx[3]={0,0,0};
    int enemyy[3]={0,0,0};
    int explosionx[3]={0,0,0};
	int explosiony[3]={0,0,0};
    //int airx;
    //int airy;

    int enemyId[3];
	int enemyID;
    
    int bulletflag[3]={0,0,0};	//bulletflag[0]=0 1 2
    int enemyflag[3]={0,0,0};
	int explosionflag[3]={0,0,0};
    int airflag=0;
    int number1flag = 0;
    int number2flag = 0;
    int number3flag = 0;
    int pressflag = 1;
    int gameoverflag = 0;
    
    int dead=0;
    int start=0;
    int numberofbullet=0;
	int j,i;
    int count=1;
    
    int enemynumber=0;
    int generate=0;
    int deadcount=0;
    int fellcount=1;
    int enemycount =0;
    int collisioncount[3]={0,0,0};
    int deadenemycount = 0;
    
    int justleft=1;
    int justright=1;
    int juststraight=1;
    int justshoot=0;
    
    //int othercount=0;//count for cloud and tree
   

    //control the movement of every enemy
	while(1) 
	{
        	libusb_interrupt_transfer(keyboard, endpoint_address,(unsigned char *) &packet,sizeof(packet),&transferred, 1);
        	//printf("transfer %d\n",transferred);
        	//printf("y0 is %d\n", xyf[1]);
        	if (transferred == 6)
		{
            		xmove=packet.leftright;
            		ymove=packet.button;
            
			//usleep(100000);
            		sprintf(keystate, "%02x %02x %02x", packet.leftright,packet.updown, packet.button);
            		printf("%s\n", keystate);
			
        	}
                    

	

		if (!start)
		{	//printf("transfer=%d\n",transferred);
            
			dead = 0;
			xyf[0]=300;
			xyf[1]=200;
            if (count==1)
            {
                if (pressflag==1)
                    pressflag = 0;
                else
                    pressflag = 1;
            }
			if(xyf[25]>0)
           			xyf[25]--;
			else
	   			xyf[25]=40;
			if (xyf[2]<6)
			{			
				xyf[2]++;
			}
			else
				xyf[2]=1;
			if (packet.button)
			{
				start = 1;
				xyf[2]=1;
                pressflag = 0;
			}
			write_segments(xyf);
			usleep(100000);
		
		}   
    //chara   
	if(start)
	{
	
    	if(!dead) 
	{       
		//normal movement
		if(justshoot==0&&count==6)
		{
            	if (xyf[2]<4)   
    	        //chara movement
                	xyf[2]++;
          	if(xyf[2]>=4)
			xyf[2]=1;
		//shoot	    
		}
        	if(xmove > 0x7f && xmove <= 0xef&& xyf[0]>0)//left ef--7f
        	{
            		xyf[0]=xyf[0]-2;//x1
        	}
        	if(xmove > 0x10 && xmove < 0x80&&xyf[0]<570)//right 80--10
        	{
            		xyf[0]=xyf[0]+2;//x1
        	}
        
        	if((ymove == 0x20 || ymove == 0x30) &&xyf[1]>0)
        	{
            		t2=0;
            		if ((xyf[1]-0.0003*t1*t1-0.5*t1)>0)
            		{
                		xyf[1]=xyf[1]-0.0003*t1*t1-0.5*t1;
            		}
            		else
                		xyf[1]=0;
            		t1++;
            		updown=1;
        	}
			 
        	if(ymove !=0x20 && ymove!=0x30 && xyf[1]<410)
        	{
            		t1=0;
            		if(xyf[1]+0.0003*t2*t2+0.5*t2<410)
                		xyf[1]=xyf[1]+0.0003*t2*t2+0.5*t2;
            		else
				xyf[1]=410;
            		t2++;
            		updown=0;
        	}
	
        
	//air
       	
		if (xmove > 0x7f && xmove <= 0xef&&(ymove == 0x20 || ymove == 0x30))	//left
		{	justright=1;
			juststraight=1;
			if(justleft==1)
			{airflag=1;}
			xyf[35] = xyf[0]+5;
			
                	if (count==6)
			{	justleft=0;
				if(airflag==1)
					airflag = 2;
				else
					airflag=1;
			}
		}
		if(xmove > 0x10 && xmove < 0x80 &&(ymove == 0x20 || ymove == 0x30))//right 80--10
        	{       justleft==1;
			juststraight=1;
			if(justright==1)
			{airflag=3;}
			xyf[35] = xyf[0]-16;
			
                	if (count==6)
			{	justright=0;
				if(airflag==3)
					airflag = 4;
				else
					airflag=3;
			}
        	}
		if((ymove == 0x20 || ymove == 0x30)&&!(xmove > 0x7f && xmove <= 0xef)&&!(xmove > 0x10 && xmove < 0x80) )//up
		{	justleft=1;
			justright=1;
			if(juststraight==1)
			{airflag=5;}
			xyf[35] = xyf[0]-5;
			
		        
                	if (count==6)
			{	juststraight=0;
				if(airflag==5)
					airflag = 6;
				else
					airflag=5;
			}
		}
        	if(!(ymove == 0x20 || ymove == 0x30) )//down
        	{
			airflag=0;
		}
      
      	
      
      //bullet initialization
      
        if ((ymove == 0x10 || ymove == 0x30) && numberofbullet < 3 && justshoot == 0)//at most 3 bullet
        {
            	justshoot = 1;
            	numberofbullet++;
	    	xyf[2]=4;
            	
            	for(i = 0; i < 3; i++)//search for 3 which bullet is blank then add the new bullet to it
            	{
                	if(bulletflag[i] == 0)	
                    	j = i;		
            	}   
                bulletx[j]=xyf[0]+70;  //init value
                bullety[j]=xyf[1]+15;
                bulletflag[j]=1;    //when bullet disappaer flag[j]=0
      	}

			



		//if button loosed set justshoot
	if(ymove != 0x10 && ymove != 0x30)
       	{
             	justshoot=0;
		//xyf[2]=1;
      	}

	
		//bullet movement
	for(i=0; i<3;i++)
        {
		if(bulletflag[i] != 0)//if bullet exists
                {
			bulletx[i]=bulletx[i]+2;
                    	if(count == 6)//if its time to change flag
                    	{
                        	
				if (bulletflag[i] == 1) //flag0: not exist flag1: bulletA flag2: bulletB
                            		bulletflag[i] = 2;
                        	else
                            		bulletflag[i] = 1;
			}
                    	if(bulletx[i] > 640)//bullet has move out of the screen
			{
                        	bulletx[i]=0;
                        	bulletflag[i]=0;
                        	numberofbullet--;
			}
		}
	}
	

        
                
                
                
        //generation of enemy using random function: random y and random enemy ID
	
        if(enemynumber < 3)//at most 3 enemy
        {
		
		enemycount++;
		
	    if(enemycount>50)
	    {
            	generate = (rand()%15);
            	if (generate == 5||enemycount>1000)//do generation randomly
            	{
			enemycount = 0;
                	enemynumber++;
                	enemyID = (rand()%2)+1;//random generate enemyID (0-2) standfor different shape of enemy
                
                	for(i=0;i<3;i++)//search for which enemy position is blank then add the new bullet to the
                	{
                    		if(enemyflag[i] == 0)
                        	j = i;
                        
                	}   
                    	enemyId[j] = enemyID; //chose enemy 0 1 2
                    	enemyx[j]=740;//from the rightside of the screen
                    	enemyy[j]=((rand()%(4))+1)*96;//random y
                    	enemyflag[j]=1;//flag set to 1 meaning display
               	}
	    }
     	}
        
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

			
        //movement
//enemy
	for(i=0; i<3;i++)
	{
		if(enemyflag[i] != 0)//if enemy exists
		{ 
			if(count < 5)//if its time to change loc and flag
			{	
                               	enemyx[i]-=2;
				enemyy[i]+=2;	   
			}
                     	else
			{
				enemyx[i]-=2;
				enemyy[i]-=2;
			}
			if(count == 4)
			{	
                        	if(enemyflag[i] == 1)
					enemyflag[i] = 2;
				else
					enemyflag[i] = 1;
			}
			if(enemyx[i] < 10)//if the enemy has move out of the screen
			{
				enemyx[i]=0;
				enemyflag[i]=0;
                enemynumber--;
			}
		}
	}
        
        
//////////////////////////////collision between bullet and enemy, supposed at most 3 enemies in the screen
	
        for(i=0; i<3; i++)
                             
			   //  if(bulletflag[i])//only displayed bullet could be in collision
        {
           	for(j=0; j<3; j++)
            {
					//if position overlap,(supposed that every enemy is 50*50) and flag is 1||2
                	if (bulletx[i]+10  > enemyx[j]-100&&bulletx[i]<enemyx[j]-40 && (bullety[i]+10 >enemyy[j] &&
                        bullety[i] < enemyy[j] + 60) && bulletflag[i] != 0 && (enemyflag[j]==1||enemyflag[j]==2))
                	{
                        bulletflag[i] = 0;
                        numberofbullet--;
                        enemyflag[j]=0;
                        enemynumber--;
                        explosionflag[j] = 1;
                        deadenemycount++;
                        explosionx[j] =enemyx[j]-30;
                        explosiony[j] =enemyy[j];
                	}
                	if (explosionflag[j] && collisioncount[j] == 6)//if collision happened?
                	{
                   	 	
                        explosionflag[j] = 0;
                        explosionx[j] =0;
                        explosiony[j] =0;
                        collisioncount[j]=0;
                	}
            }
        }
        
        
////////////////////////////////////////collision between chara and enemy        
        for(i=0; i<3; i++)
        {
                //if position overlap,(supposed that every enemy is 50*50) and flag is 1||2
                if (xyf[0] + 40 > enemyx[i]-100&&xyf[0]<enemyx[i] && (xyf[1] + 40 > enemyy[i] && xyf[1] < enemyy[i] + 40) 
			&& (enemyflag[i]==1||enemyflag[i]==2)&&(xyf[2]<6))
                {
                    	//bulletflag[i] = 0;
                    	//numberofbullet--;
                    	//enemyflag[j] = 3;
                    	xyf[2] =6 ;//
			dead=1;
		    	//airflag=0;
                }
	}


   if(fellcount==6)
        {	
		if(justshoot)
		{		
            	if(xyf[2]==4)
                	xyf[2]=5;
		else if(xyf[2]==5)
                	xyf[2]=4;
		}
	        
	
	}





   }//not dead



	else//dead
	{//falling
		airflag=0;
		bulletflag[0]=0;
		bulletflag[1]=0;
		bulletflag[2]=0;
		enemyflag[0]=0;
		enemyflag[1]=0;
		enemyflag[2]=0;
		explosionflag[0]=0;
		explosionflag[1]=0;
		explosionflag[2]=0;
		numberofbullet=0;
		enemynumber=0;
                if ((count == 6||count == 2)&&xyf[2]>=6&&xyf[1]<380)//if collision happened?
                {
                    
			  
			xyf[1]+=6;
		    	if(xyf[2] ==6)
                    		xyf[2] = 7;
                    	if(xyf[2] ==7)
                    		xyf[2] = 6;
  
                }
		if(count == 6 && xyf[1]>=380)
		{	gameoverflag = 1;
			if(xyf[2]<11)
			{
		       		xyf[2]++;
				xyf[0]+=8; 
			}
					
		}
		if (xyf[2]==11&&deadcount==0)
		{
			deadcount=1;
			//start=0;
			//goto restart;
		}
		if(deadcount==60)
		{
            deadcount=0;
            start=0;
            pressflag = 1;
            gameoverflag = 0;
		 //dead=0;
		}
		
    	}//dead
   
        
        

   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        
	}//start
	if(fellcount==6)
	{//brick movement
		if(xyf[25]>0)
           		xyf[25]--;
		else
	   		xyf[25]=40;
	}
       
	xyf[3] = bulletx[0];
	xyf[4] = bullety[0];
	xyf[5] = bulletflag[0];
	xyf[6] = bulletx[1];
	xyf[7] = bullety[1];
	xyf[8] = bulletflag[1];
	xyf[9] = bulletx[2];
	xyf[10] = bullety[2];
	xyf[11] = bulletflag[2];
	xyf[12] = enemyx[0];
	xyf[13] = enemyy[0];
	xyf[14] = enemyflag[0];
	xyf[15] = enemyId[0];
	xyf[16] = enemyx[1];
	xyf[17] = enemyy[1];
	xyf[18] = enemyflag[1];
	xyf[19] = enemyId[1];
	xyf[20] = enemyx[2];
	xyf[21] = enemyy[2];
	xyf[22] = enemyflag[2];
	xyf[23] = enemyId[2];
	//xyf[24] = 
	//xyf[25] = 
	xyf[26] = explosionx[0];
	xyf[27] = explosiony[0];
	xyf[28] = explosionflag[0];
	xyf[29] = explosionx[1];
	xyf[30] = explosiony[1];
	xyf[31] = explosionflag[1];
	xyf[32] = explosionx[2];
	xyf[33] = explosiony[2];
	xyf[34] = explosionflag[2];
	
	xyf[36] = xyf[1]+58;
	xyf[37] = airflag;
        xyf[38] = deadenemycount / 100;  //number1 398
        xyf[39] = (deadenemycount / 10) % 10; //number2
        xyf[40] = deadenemycount % 10;//number3
        xyf[41] = pressflag;//press
        xyf[42] = gameoverflag;//game over
        write_segments(xyf);
        
	//printf("charaflag %d\n", xyf[2]);
	//printf("airflag %d\n",airflag);
	//printf("enemy1 %d\n",xyf[14]);
	//printf("enemy2 %d\n",xyf[18]);
	//printf("enemy3 %d\n",xyf[22]);
        if (count<8)
            count++;
        else
            count=1;

	for(i=0;i<3;i++)
	{
	if (explosionflag[i]==1)
	{
	    
            collisioncount[i]++;
	  
	}
	}

	if (fellcount<20)
            fellcount++;
        else
            fellcount=1;

        usleep(17000);/////////

	if(deadcount>=1)
	{
	 deadcount++;
	}

}
  
  
  printf("VGA LED Userspace program terminating\n");
  return 0;

}

