#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 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 = 2;	//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;



    if (flag == 0) {

        //implement normal procedure(move down the player)




        for (; ; ) {

        	//printf("%d", time);
        	counter--;
        	counter2--;

        	if(counter2 == 0){
        		counter2 = 215000;	//215000 times the clock time
        		gameTime = gameTime + 1;
        		if(gameTime%10 == 0){

            		printf("%d seconds since game starts \n", gameTime);
        		}
        	}

        	if(counter == 0){

        		counter = 100000000000000;

        		//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
				}


        	}


        }











    }else if(flag == 1){
        //implement move procedure(move up the player)
    }
    else{
        //implement shot procedure(create bullet)
    }
}
