#include <io.h>
#include <system.h>
#include <stdio.h>
#include <time.h>

#define IOWR_SRAM_DATA(base, offset, data) \
  IOWR_16DIRECT(base, (offset) * 2, data)
#define IORD_SRAM_DATA(base, offset) \
  IORD_16DIRECT(base, (offset) * 2)
#define IOWR_SRAM_SPEED(base, data) \
  IOWR_16DIRECT(base + 32, 0, data)

int main()
{

    int flag = 0;   // use to determine what state are we


    int gameTime = 0;   // time count
    int score = 0;  // score count

    int deadFlag;  //indicates player has been created
    int playerXCoordinate;   //player's leftmost upmost coordinate
    int playerYCoordinate;
    int life;   //indicate how many life still left
    int openMouthTime;

    int bossFlag;    //indicates boss has been created
    int bossXCoordinate; //boss's leftmost upmost coordinate
    int bossYCoordinate;
    int bossLife;

    int enemyCount; // number of enemies in the screen up to 8 enemies

    int enemyFlag[9];
    int enemyXCoordinate[9];  //enemies' leftmost upmost coordinate
    int enemyYCoordinate[9];
    int fireworkTime;

    int bulletFlag; //indicate bullet created
    int bulletXCoordinate;
    int bulletYCoordinate;


    int hitXCoordinate; //where to put on hit effect
    int hitYCoordinate;

    int collisionXCoordinate;   //where to put on collision effect
    int collisionYCoordinate;

    int gameoverXCoordinate;    //where to put on game over picture
    int gameoverYCoordinate;

    int playerXSpeed;	//speed for everything
    int playerYSpeed;
    int enemyXSpeed;
    int enemyYSpeed;
    int bossXSpeed;
    int bossYSpeed;
    int bulletXSpeed;

    int xLowBound = 0;		// bound for the screen pixels
    int xHighBound = 640;
    int yLowBound = 0;
    int yHighBound = 480;
    //int sound = 0;

    long counter;	// raise the clock to make a loop longer
    int counter2;	// counter to make a loop same lenth as real time

    //int counter2 = 100000;
    int counter3 = 10000;
    int shine =0;	// variable for dead effect

    //int silence = 0;
    //int sound = 0;


    //int soundByte = IORD_16DIRECT(audio_BASE, 0);
    //printf(soundByte);

    //flag = GET_FLAG get flag from hardware


    playerXCoordinate = 40;		// init positions
	playerYCoordinate = 360;
	bossXCoordinate = 550;
	bossYCoordinate = 400;
	bulletXCoordinate = 600;
	bulletYCoordinate = 480;

	playerYSpeed = 1;	//init speeds
	enemyXSpeed = 3;
	bossXSpeed = 0;
	bossYSpeed = 0;
	bulletXSpeed = 4;

	deadFlag = 0;	//int flags
	bossFlag = 0;
	bulletFlag = 0;
	life = 3;

	int i = 0;	//init for enemyflags
	int j = 0;
	for(i = 0; i < 10; i++){
		enemyFlag[i] = 0;
		enemyXCoordinate[i] = 800;
		enemyYCoordinate[i] = 800;
	}
	enemyCount = 0;


	counter = 10000;	//init counter and counter2
	counter2 = 40000;

	srand(time(NULL));

	IOWR_SRAM_DATA(VGA_BASE,31, 0);
	IOWR_SRAM_DATA(VGA_BASE,30, 0);
	openMouthTime = 0;
	fireworkTime = 0;


        for (; ; ) {


        	int a = IORD_16DIRECT(AUDIOSLAVE_BASE,0);


        	 if( a < 1500 || a >64035 || (a>32000 && a< 33000))
        	        {
        	        	counter2--;
        	        	//counter3 = 10000;
        	        	if(counter2==0){
        	        		if(flag == 1 || flag == 2|| flag == 3 || flag == 4|| flag ==5){
        	        			flag = 0;

        	            		counter2 = 15000;
        	        		}else{

        	            		flag = 0;
        	            		counter2 = 100000;
        	        		}
        	        	}
        	        }else{
        	        	counter2 = 15000;
        	        	counter3--;

        	        	if(counter3==0){

        	        		counter3 = 2500;
        	        		flag = flag + 1;

        	        	}
        	            //printf("%d\n",a);
        	        }
        	    }
//        	counter--;
//        	counter2--;
//
//        	if(counter2 == 0){
//        		counter2 = 2150000;	//215000 times the clock time
//        		gameTime = gameTime + 1;
//        		if(gameTime%10 == 0){
//
//            		printf("%d seconds since game starts \n", gameTime);
//        		}
//        	}
//
//        	if(counter == 0){
//
//        		counter = 30000;
//        		//printf("_________________________________________________________-");
//
//
//
//        	}
//
//
//        }

        //increment score
        				score = score + 10;
        				//display score
        				//IOWR_SRAM_DATA(VGA_BASE,,score);




        				//player moving
        				if(playerYCoordinate - yLowBound <= 100){
        					playerYSpeed = - playerYSpeed;
        				}
        				if(yHighBound - playerYCoordinate <= 90){
        					playerYSpeed = - playerYSpeed;
        				}

        				playerYCoordinate = playerYCoordinate - playerYSpeed;

        				//super mode after dead
        				if(deadFlag == 1){
        					if(shine == 10 || shine == 20 || shine == 30 || shine == 40 || shine == 50 || shine == 60 || shine == 70 || shine == 80 || shine == 90 ){
        						IOWR_SRAM_DATA(VGA_BASE, 2, 800);
        						IOWR_SRAM_DATA(VGA_BASE, 13, 800);
        						shine = shine + 1;
        					}else if(shine == 100){
        						IOWR_SRAM_DATA(VGA_BASE, 2, 800);
        						IOWR_SRAM_DATA(VGA_BASE, 13, 800);
        						deadFlag = 0;
        						shine = 0;
        						printf("super mode over \n");
        					}else{
        						IOWR_SRAM_DATA(VGA_BASE, 2, playerXCoordinate);
        						IOWR_SRAM_DATA(VGA_BASE, 13, playerYCoordinate);
        						shine = shine + 1;
        					}
        				}else{
        					IOWR_SRAM_DATA(VGA_BASE, 2, playerXCoordinate);
        					IOWR_SRAM_DATA(VGA_BASE, 13, playerYCoordinate);
        				}




        				//enemy created


        				int randNumberSeed = rand()%1000;
        				int randNumber = randNumberSeed%100;
        				//printf("randNumber is %d \n", randNumber);

        				if(randNumber  > 97 && enemyCount < 5){
        					//rand is from 0-99, thus 0.01% runs created enemy
        					//create enemy of No.(enemyCount + 1)

        					i = 0;
        					while(enemyFlag[i] == 1 && i<5){
        						i++;
        					}

        					enemyXCoordinate[i] = 620;
        					enemyYCoordinate[i] = (randNumberSeed/3) + 10;

        					if( enemyYCoordinate[i] >= 100){

        						enemyFlag[i] = 1;
        						for(j=0; j< i; j++){
        							if(abs(enemyYCoordinate[i] - enemyYCoordinate[j]) <= 80 && abs(enemyXCoordinate[i] - enemyXCoordinate[j] <= 60)){
        								enemyFlag[i] = 0;
        							}
        						}
        						if(i < 3){
        							for(j=i+1; j< 3; j++){
        								if(abs(enemyYCoordinate[i] - enemyYCoordinate[j]) <= 80 && abs(enemyXCoordinate[i] - enemyXCoordinate[j] <= 60)){
        									enemyFlag[i] = 0;
        								}
        							}

        						}

        						printf("an enemy emerge at %d, there are %d enemies \n",enemyYCoordinate[i], enemyCount + 1);
        						if(enemyFlag[i] == 1){

        							enemyCount++;
        						}
        					}

        				}


        				//enemy engaging
        				for(i = 0; i < 3; i++){
        					if(enemyFlag[i] == 1){
        						enemyXCoordinate[i] = enemyXCoordinate[i] - enemyXSpeed;
        						if(enemyXCoordinate[i] < 20){
        							enemyFlag[i] = 0;
        							enemyCount --;

        							IOWR_SRAM_DATA(VGA_BASE, 3+i , 800);
        							IOWR_SRAM_DATA(VGA_BASE,12-i, 800);
        							printf("an enemy passed, there are %d enemies \n", enemyCount + 1);
        						}else{
        						//give it to hardware
        						IOWR_SRAM_DATA(VGA_BASE,3+i, enemyXCoordinate[i]);
        						IOWR_SRAM_DATA(VGA_BASE,12-i, enemyYCoordinate[i]);
        						}
        					}
        				}



        				//boss created
        				if(gameTime > 1 && gameTime < 3 && bossFlag == 0){
        					//create boss only between a time
        					bossFlag = 1;
        					printf("boss created \n");
        					bossLife = 1000;


        					//assign position

        					bossXCoordinate = 550;
        					bossYCoordinate = 400;
        					IOWR_SRAM_DATA(VGA_BASE,30, 0);
        			        IOWR_SRAM_DATA(VGA_BASE, 0, 550);
        			        IOWR_SRAM_DATA(VGA_BASE, 15, 400);
        				}
        				if(gameTime > 25 && gameTime < 35){
        					IOWR_SRAM_DATA(VGA_BASE,30, 1);
        				}

        				if(gameTime > 35 && gameTime < 37){
        					IOWR_SRAM_DATA(VGA_BASE,30, 2);
        					bossYSpeed = -2;
        					bossXSpeed = 1;
        					bossLife = 3;
        				}
        				//boss engaging
        				if(bossFlag == 1){

        			        if(bossYCoordinate - yLowBound <= 100){
        			        	bossYSpeed = -bossYSpeed;
        			        }
        			        if(yHighBound - bossYCoordinate <= 79){
        			        	bossYSpeed = -bossYSpeed;
        			        }


        					bossXCoordinate = bossXCoordinate - bossXSpeed;
        					bossYCoordinate = bossYCoordinate + bossYSpeed;

        					if(bossXCoordinate < 20){
        						bossFlag = 0;
        						printf("boss passed \n");
        				        IOWR_SRAM_DATA(VGA_BASE, 0, 800);
        				        IOWR_SRAM_DATA(VGA_BASE, 15, 800);


        				    	bossXCoordinate = 550;
        				    	bossYCoordinate = 400;
        					}else
        					{

        						//give it to hardware
        				        IOWR_SRAM_DATA(VGA_BASE, 0, bossXCoordinate);
        				        IOWR_SRAM_DATA(VGA_BASE, 15, bossYCoordinate);
        					}


        				}



        				// create bullet
        		        if(bulletFlag == 0 ){
        		        	bulletXCoordinate = 80;
        		        	bulletYCoordinate = playerYCoordinate + 50;
        		        	bulletFlag = 1;
        		        	IOWR_SRAM_DATA(VGA_BASE,31, 1);
        		        	openMouthTime = gameTime;

        		        }

        		        if(gameTime - openMouthTime > 0){
        		        	IOWR_SRAM_DATA(VGA_BASE,31, 0);
        		        }

        				//bullet engaging
        				if(bulletFlag == 1){

        					bulletXCoordinate = bulletXCoordinate + bulletXSpeed;

        					if(bulletXCoordinate > xHighBound){
        						bulletFlag = 0;
        					}
        					//give it to hardware

        			        IOWR_SRAM_DATA(VGA_BASE, 1, bulletXCoordinate);
        			        IOWR_SRAM_DATA(VGA_BASE, 14, bulletYCoordinate);
        				}


        				//hit boss happens
        				if(bulletFlag == 1 && bossFlag == 1 && abs(bulletXCoordinate-bossXCoordinate) <= 40 && bulletYCoordinate - bossYCoordinate <= 80 && bulletYCoordinate - bossYCoordinate >= -25) {

        						//assign hit position
        						printf("hit boss happen \n");
        						bossLife = bossLife - 1;
        						if(bossLife == 0){
        							// boss died
        							bossFlag = 0;
        							IOWR_SRAM_DATA(VGA_BASE,30, 0);
        					        //IOWR_SRAM_DATA(VGA_BASE, 0, 550);
        					        //IOWR_SRAM_DATA(VGA_BASE, 15, 400);

        					        IOWR_SRAM_DATA(VGA_BASE, 7 , bossXCoordinate);
        					        IOWR_SRAM_DATA(VGA_BASE, 8 , bossYCoordinate);
        					        fireworkTime = gameTime;
        						}
        						bulletFlag = 0;

        				        IOWR_SRAM_DATA(VGA_BASE, 0, 800);
        				        IOWR_SRAM_DATA(VGA_BASE, 15, 800);
        						score = score + 1000;

        						//create hitposition

        						//give it to hardware
        					}


        				//hit enemy happens
        				for(i=0; i<5; i++){

        					if(bulletFlag == 1 && enemyFlag[i] == 1 && abs(bulletXCoordinate-enemyXCoordinate[i]) <= 40 && bulletYCoordinate - enemyYCoordinate[i] <= 80 && bulletYCoordinate - enemyYCoordinate[i] >= -25) {

        							//assign hit position
        							printf("hit enemy happen , there are now %d enemies \n", enemyCount);
        							enemyFlag[i] = 0;
        							bulletFlag = 0;
        							enemyCount--;
        					        IOWR_SRAM_DATA(VGA_BASE, 3+i , 800);
        					        IOWR_SRAM_DATA(VGA_BASE, 12-i , 800);
        							score = score + 100;

        					        IOWR_SRAM_DATA(VGA_BASE, 7 , enemyXCoordinate[i]);
        					        IOWR_SRAM_DATA(VGA_BASE, 8 , enemyYCoordinate[i]);
        					        fireworkTime = gameTime;
        							//create hitposition

        							//give it to hardware
        						}
        				}


        				if(gameTime - fireworkTime > 0){

        			        IOWR_SRAM_DATA(VGA_BASE, 7 , 800);
        			        IOWR_SRAM_DATA(VGA_BASE, 8 , 800);
        				}


        				//collision boss happens
        				if(deadFlag == 0 && bossFlag == 1 && bossXCoordinate - playerXCoordinate>0 && bossXCoordinate - playerXCoordinate <= 40 && abs(bossYCoordinate - playerYCoordinate) <= 60){
        					//assign collision happens
        					deadFlag = 1;

        					life = life - 1;

        					printf("player is dead contacting boss, has life %d \n", life);
        					//create collision effect
        					//give it to hardware
        				}

        				//collision enemy happens
        				for(i=0; i < 5; i++){

        					if(deadFlag == 0 && enemyFlag[i] == 1 && enemyXCoordinate[i] - playerXCoordinate>0 && enemyXCoordinate[i] - playerXCoordinate <= 40 && abs(enemyYCoordinate[i] - playerYCoordinate) <= 60){
        						//assign collision happens
        						deadFlag = 1;
        						enemyFlag[i] = 0;
        						enemyCount--;
        						life = life - 1;

        						printf("player is dead contacting enemy, has life %d \n", life);
        				        IOWR_SRAM_DATA(VGA_BASE, 3 + i, 800);
        				        IOWR_SRAM_DATA(VGA_BASE, 12 - i, 800);
        						//create collision effect
        						//give it to hardware
        					}
        				}


        				//game over happen
        				if(life == 0){
        					//create game over
        					printf("no life. Game over \n");
        					printf("score is %d", score);
        					//give it to hardware
        				}



        				//finish game
        				if(gameTime > 80){
        					// player survive
        					gameTime = 0;
        					openMouthTime = 0;
        					bossYSpeed = 0;
        					bossXSpeed = 0;
        					bossLife = 1000;
        					if(life > 0){

        						score = score + life * 1000;
        					}
        					life = 3;
        					printf("time out . Game over \n");
        					printf("score is %d", score);
        					//printf("250s time has past. Game over");
        					// give it to hardware
        				}
}


