

////*
// * All Invaders Are Belong To Us 
// *
// */

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

#define IOWR_VGA_DATA(base, offset, data) \
    IOWR_16DIRECT(base, (offset)*2, data);

#define INTERVAL 10
#define HOME_INCREMENT 4 
#define ALIEN_INCREMENT 5
#define LEFT_BOUNDARY 0 
#define RIGHT_BOUNDARY 595
#define HOME_V_START 440
#define HOME_MISSILE_BOUNDARY 30
#define ALIEN_MISSILE_BOUNDARY 440
#define HOME_MISSILE_INC 15
#define ALIEN_MISSILE_INC 5
#define MAX_MISSILES 10 


#define WAVE_RIGHT_BOUNDARY 264
#define WAVE_FINAL_ROW 300
//#define WAVE_DELAY 10000

#define ALIEN_LENGTH 16
#define ALIEN_WIDTH 16
#define BARRICADE_LENGTH 32 
#define BARRICADE_WIDTH 32
#define ALIEN_GAP 16
#define NUM_ALIENS_PER_ROW 12 
#define NUM_ROWS 5

#define BARRICADE1_H_COORD 125
#define BARRICADE1_V_COORD 375
#define BARRICADE2_H_COORD 225
#define BARRICADE2_V_COORD 375
#define BARRICADE3_H_COORD 325
#define BARRICADE3_V_COORD 375
#define BARRICADE4_H_COORD 425
#define BARRICADE4_V_COORD 375

#define NUM_H_BLOCKS_BARRICADE 4 
#define BARRICADE_BLOCK_LENGTH 2 
#define BARRICADE_BLOCK_WIDTH 8

#define INIT_WAVE_DELAY 3000
#define WAVE_DELAY_DEC 0
#define INIT_ACTIVE_MISSILES 0

#define ALIEN_CLOCK_FACTOR 1

//global variables for difficulty
int wave_delay = INIT_WAVE_DELAY;
int alien_missile_inc = ALIEN_MISSILE_INC;
 
//global variables
unsigned char code;
int val = 0; 
int codeFlag = 0;
int direction = 0;
int wave_h = 60;
int wave_v = 30;
int home_missile_x = 0; 
int home_missile_y = 0;
int rowId = 0;
int max_active_missiles = INIT_ACTIVE_MISSILES;
int randCol = 0; 
int randRow = 0;

int rowIdx = 0; 
int colIdx = 0;
int alienIdx = 0;
int m_idx = 0; 

int barricade_collision = 0;
int barricade_col_id = 0;
int barricade_block_idx = 0;

int counter = 10000;
int alien_clock_factor = 1; 
int alien_delay_counter = 0;

int alien_status[4];

int current_score = 0;
int display_score;
int save_score;
int lives1 = 3;
int save_lives;
int level = 0;

int cdelay=0;
int ddelay=0;

int first_alien_incol[NUM_ALIENS_PER_ROW];

int barricade_v_coords[4]; 
int barricade_h_coords[4]; 

// change 
int first_barricade_block[4][NUM_H_BLOCKS_BARRICADE]; 
// change 
int last_barricade_block[4][NUM_H_BLOCKS_BARRICADE]; 

int active_missiles[MAX_MISSILES]; 
int alien_missile_x[MAX_MISSILES]; 
int alien_missile_y[MAX_MISSILES]; 

int num_active_missiles = 0; 

int restart = 0;
int key_delay=0;

//game state values// 
int game_state=1; 
int ent_count=2; 
char state = 'I';
int state_reset = 0;
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
void restart_game()
{
    val = 0; 
    IOWR_16DIRECT(VGA_BASE, 0,val);
    IOWR_32DIRECT(AUDIO_BASE,0,0x00000069);
    wave_delay = INIT_WAVE_DELAY;
    max_active_missiles = INIT_ACTIVE_MISSILES;
    counter = 10000;   
    alien_delay_counter = 0;       
    alien_clock_factor = ALIEN_CLOCK_FACTOR;    
    level = 0; 
    
    alien_missile_inc = ALIEN_MISSILE_INC;
                  
    cdelay = 0; 
    ddelay = 0;
                  
                       
    codeFlag = 0;
    direction = 0;
    wave_h = 60;
    wave_v = 30;
    int kk = 0; 
    for ( ; kk < 4 ; kk++ ) { 
        alien_status[kk] = 0xFFFF;
    }
    
    home_missile_x = 0; 
    home_missile_y = 0;
    IOWR_VGA_DATA(VGA_BASE, 9, home_missile_x);
    IOWR_VGA_DATA(VGA_BASE, 10, home_missile_y);
    
    current_score = 0;
    display_score = current_score;
    IOWR_VGA_DATA(VGA_BASE, 3, display_score);
    IOWR_VGA_DATA(VGA_BASE, 4, display_score);
    IOWR_VGA_DATA(VGA_BASE, 5, display_score);
    IOWR_VGA_DATA(VGA_BASE, 6, display_score);
    IOWR_VGA_DATA(VGA_BASE, 7, display_score);
    //for lives
    lives1 = 3;
    IOWR_VGA_DATA(VGA_BASE, 8, lives1);
    
    int ii = 0; int jj = 0; 

    for ( ii = 0 ; ii < NUM_ALIENS_PER_ROW; ii++ ) 
    {
        first_alien_incol[ii] = NUM_ROWS; 
    }
    
    for ( ii = 0; ii < 4 ; ii++ ) 
    { 
        for ( jj = 0 ; jj < NUM_H_BLOCKS_BARRICADE; jj++ ) //TODO: #define these constants  
        {
            first_barricade_block[ii][jj] = 1;
            last_barricade_block[ii][jj] = 32/BARRICADE_BLOCK_LENGTH;
        }
        
        
    }
    
    barricade_v_coords[0] = BARRICADE1_V_COORD; 
    barricade_v_coords[1] = BARRICADE2_V_COORD; 
    barricade_v_coords[2] = BARRICADE3_V_COORD; 
    barricade_v_coords[3] = BARRICADE4_V_COORD; 
    
    barricade_h_coords[0] = BARRICADE1_H_COORD; 
    barricade_h_coords[1] = BARRICADE2_H_COORD; 
    barricade_h_coords[2] = BARRICADE3_H_COORD; 
    barricade_h_coords[3] = BARRICADE4_H_COORD; 
    
    
//#define BARRICADE1_V_COORD 375
//#define BARRICADE2_H_COORD 225
//#define BARRICADE2_V_COORD 375
//#define BARRICADE3_H_COORD 325
//#define BARRICADE3_V_COORD 375
//#define BARRICADE4_H_COORD 425
//#define BARRICADE4_V_COORD 375; 
int barricade_h_coords[4];
    
    for (ii = 0  ; ii < MAX_MISSILES; ii++ ) 
    {
        active_missiles[ii] = 0;
        alien_missile_x[ii] = 0; 
        alien_missile_y[ii] = 0;
    }
    
    num_active_missiles = 0; 
    
    IOWR_16DIRECT(VGA_BASE, 0,0);
    restart = 0;
    key_delay=0;
    state_reset=0;  
}


void new_level()
{
    level++;
    
    cdelay = 0; 
    ddelay = 0;
     
    printf("level = %d\n",level);
    IOWR_VGA_DATA(VGA_BASE,48,(level - level%10)/10);
    IOWR_VGA_DATA(VGA_BASE,49,level%10);
    IOWR_32DIRECT(AUDIO_BASE,0,0x00000069);
    
    val = 0; 
    IOWR_16DIRECT(VGA_BASE, 0,val);
    codeFlag = 0;
    direction = 0;
    wave_h = 60;
    wave_v = 30;
    
    alien_delay_counter = 0;       
    
    if ( alien_clock_factor > 1 ) 
        alien_clock_factor--;    
    
    int kk = 0; 
    for ( ; kk < 4 ; kk++ ) { 
        alien_status[kk] = 0xFFFF;
    }
    
    home_missile_x = 0; 
    home_missile_y = 0;
    IOWR_VGA_DATA(VGA_BASE, 9, home_missile_x);
    IOWR_VGA_DATA(VGA_BASE, 10, home_missile_y);
    

    if (wave_delay > 1000 ) 
         wave_delay -= WAVE_DELAY_DEC;
    if(max_active_missiles<MAX_MISSILES)
    {
          max_active_missiles++;
    }else { 
        if ( alien_missile_inc < 12 )
        { 
            alien_missile_inc += 2;
            max_active_missiles = 6;
        } 
        
           
    }
    //for lives
  
    
    int ii = 0; int jj = 0; 

    for ( ii = 0 ; ii < NUM_ALIENS_PER_ROW; ii++ ) 
    {
        first_alien_incol[ii] = NUM_ROWS; 
    }
    
    for ( ii = 0; ii < 4 ; ii++ ) 
    { 
        for ( jj = 0 ; jj < NUM_H_BLOCKS_BARRICADE; jj++ ) //TODO: #define these constants  
        {
            first_barricade_block[ii][jj] = 1;
            last_barricade_block[ii][jj] = 32/BARRICADE_BLOCK_LENGTH;
        }
    }
    
    for (ii = 0  ; ii < MAX_MISSILES; ii++ ) 
    {
        active_missiles[ii] = 0;
        alien_missile_x[ii] = 0; 
        alien_missile_y[ii] = 0;
    }
    
    num_active_missiles = 0; 
    
    IOWR_16DIRECT(VGA_BASE, 0,0);
    restart = 0;
    key_delay=0;
    state_reset=0;
    state = 'I';
    
 
}

int alien_phalanx(direction)
{
    switch (direction)
    {
        case 0: //Moving Right
            IOWR_VGA_DATA(VGA_BASE,1,wave_h); 
            IOWR_VGA_DATA(VGA_BASE,2,wave_v);
            
            if(wave_h < WAVE_RIGHT_BOUNDARY){
                wave_h++ ;
                IOWR_16DIRECT(VGA_BASE,2,wave_h);
            }
            else{
                direction = 1; //Turn around
                if (wave_v < WAVE_FINAL_ROW)//advance forward
                {
                    wave_v+=5;
                    IOWR_16DIRECT(VGA_BASE,4,wave_v);
                }
            } 
            break;
        case 1: //Moving Left
            if(wave_h > 0){
                wave_h--;
                IOWR_16DIRECT(VGA_BASE,2,wave_h);
            }
            else{
                direction = 0; //Turn around
                if (wave_v < WAVE_FINAL_ROW)//advance forward
                {
                    wave_v+=5;
                    IOWR_16DIRECT(VGA_BASE,4,wave_v);
                }
            }
            break;
    }
    return direction;
}




char read_key()
{
    code=IORD_8DIRECT(PS2_BASE,4);
    printf("scan code is %x\n", code);   
    switch (code)
    {
        case 0x29:
            //printf("space ! \n");

            if (codeFlag == 0)
            {
                if (state == 'I')
                    state = 'F';
        
                if (state == 'L')
                    state = 'G';
        
                if (state == 'R')
                    state = 'H';
        
                //codeFlag = 1;
            }
            else 
            {
                if(codeFlag == 2)
                {
					if (state == 'G') 
                        state = 'L';
					else if (state == 'H') 
                        state = 'R';
                    else if (state == 'F')
                       state = 'I';
					//codeFlag = 1;
                }
                codeFlag = 0;   
            }
            break;

        case 0x5a: 
              
                if ( game_state == 3 ) 
                {
                    if ( codeFlag == 0 ) { 
                       game_state=1;
                       IOWR_VGA_DATA(VGA_BASE,52 , game_state);
                       //codeFlag = 1; 
                    }
                    else 
                    {
                     codeFlag = 0;   
                    }
                
                }
                else if((ent_count%2)==0)
                {
                    //printf("\n1:ent count %d",ent_count);
                    //toggle enter button state
                    ent_count++;
                    //change game state to 'playing'
                    game_state=2;
                    IOWR_VGA_DATA(VGA_BASE,52 , game_state);
                     //printf("\n2:ent count %d",ent_count);
                     //codeFlag = 0;
                }
                else if((ent_count%2)!=1)
                {
                     printf("\n3:ent count %d",ent_count);
                    ent_count++;
                    IOWR_VGA_DATA(VGA_BASE, 0xFFFF, 0);
                    restart_game();
                    new_level();
                     printf("\n4:ent count %d",ent_count);
                     //codeFlag = 0;
                }
                codeFlag = 0;
            break;     
            
        case 0x6B:
          //printf("left ! \n");
                     
            if ( codeFlag == 1 ) { 
                if (state == 'I')
                    state = 'L';
        
                if (state == 'F')
                    state = 'G';
                
                if (state == 'R')
                    state = 'L';
                    
                if (state == 'H')
                    state = 'G';
                codeFlag = 0;
            }
            else {
                if(codeFlag == 2)
                {
					if (state == 'G')
                        state = 'F';
                    else if (state == 'L')
                        state = 'I'; 
                    //codeFlag = 1;
                } 
                codeFlag = 0; 
            }
            break;
        
        case 0x74:
            //printf("right ! \n");
        
            if  ( codeFlag == 1 ) { 

                if (state == 'I')
                    state = 'R';
        
                if (state == 'F')
                    state = 'H';
                
                if (state == 'L')
                    state = 'R';
                    
                if (state == 'G')
                    state = 'H';
                codeFlag = 0;
            }
            else {
                if(codeFlag == 2)
                {
                    if (state == 'H')
					   state = 'F';
                    else if (state == 'R')
                       state = 'I';
                    //codeFlag = 1; 
                }
                codeFlag = 0;   
            }                    
            break;
        case 0xE0: 
            //printf("E0 ! \n");
            codeFlag = 1;
            break;
        case 0xF0:
            codeFlag = 2;       
            break;    
        default:
            codeFlag = 0;
            break;           
    }
    printf("state change to %c\n", state);
    printf("codeFlag is %i\n\n",codeFlag); 
    return state;           
}

void response(state)
{
    switch (state)
    {
        case 'I':
            //do nothing
            break;
        case 'L':
            val -= HOME_INCREMENT; 
            if ( val < LEFT_BOUNDARY ) val += HOME_INCREMENT; 
                IOWR_16DIRECT(VGA_BASE, 0,val);
            break;
        case 'R':
            val += HOME_INCREMENT; 
            if  ( val > RIGHT_BOUNDARY ) val -= HOME_INCREMENT;
                IOWR_16DIRECT(VGA_BASE, 0,val);
            break;
        case 'F':
            if ( home_missile_y == 0 ) // means there is no active home missile
            {
                 home_missile_x = val+16; // make this a constant 
                 home_missile_y = HOME_V_START;
                 //cdelay=20000;
            }
            break;
        case 'H':
            val += HOME_INCREMENT; 
            if  ( val > RIGHT_BOUNDARY ) val -= HOME_INCREMENT;
                IOWR_16DIRECT(VGA_BASE, 0,val);
            if ( home_missile_y == 0 ) // means there is no active home missile
            {
                 home_missile_x = val+16; // make this a constant 
                 home_missile_y = HOME_V_START;
                 //cdelay=20000;
            }
            break;
        case 'G':
            val -= HOME_INCREMENT; 
            if ( val < LEFT_BOUNDARY ) val += HOME_INCREMENT; 
                IOWR_16DIRECT(VGA_BASE, 0,val);
            if ( home_missile_y == 0 ) // means there is no active home missile
            {
                 home_missile_x = val+16; // make this a constant 
                 home_missile_y = HOME_V_START;
                // cdelay=20000;
            }            
            break;           
        default:
            break;
    }
}

void delay(int time)
{
    while(time--);
}

int main()
{
   
    int num_active_cols = NUM_ALIENS_PER_ROW; 
    int end_of_level_flag = 1;
    do
    {
        //printf("Start Game!\n");
        
        restart_game();      
        IOWR_VGA_DATA(VGA_BASE, 0xFFFF, 0);
        //////////////////////////////////////
        
        //change game state to 'intro screen'//
        game_state=1;
        IOWR_VGA_DATA(VGA_BASE,52 , game_state);
        //////////////////////////////////////
        
       
//        int timer3=3;
//        IOWR_VGA_DATA(VGA_BASE,50,timer3);
//        int timer4=4;
         
        end_of_level_flag = 1; 
         
        while (lives1)
        {    
            
            
            
            if (end_of_level_flag) 
            {
                printf("End of level flag set \n");
                new_level();
                IOWR_VGA_DATA(VGA_BASE, 0xFFFF, 0);
                num_active_cols = NUM_ALIENS_PER_ROW; 
                end_of_level_flag = 0;  
            }
            
            //Commanding the alien wave phalanx
            if (counter >= wave_delay)
            {
                //printf("start \n");
                int nn = 0;
                int breachFlag = 0; 
                for ( nn = 0; nn < NUM_ALIENS_PER_ROW; nn++ ) 
                {
//                 printf("current loc = %d \n", wave_v + first_alien_incol[nn] *  ( ALIEN_LENGTH ) 
//                 +   (first_alien_incol[nn] - 1) *  ( ALIEN_GAP ) );
                 if ((first_alien_incol[nn] > 0)
                 && ( wave_v + first_alien_incol[nn] *  ( ALIEN_LENGTH ) 
                 +   (first_alien_incol[nn] - 1) *  ( ALIEN_GAP ) > BARRICADE1_V_COORD-BARRICADE_LENGTH))  
                   {
                    
                    breachFlag = 1; 
                    break;
                   } 
                }
                if ( breachFlag ) { 
                    printf("breached\n");
                    lives1 = 0;
                    continue; 
                }
                
              
                // home missile display
                if ( home_missile_y > 0 ) 
                { 
                    if ( home_missile_y < HOME_MISSILE_BOUNDARY  ) 
                    { 
                        home_missile_y = 0; 
                        home_missile_x = 0;
                    }
                    else  
                    {
                        home_missile_y -= HOME_MISSILE_INC;    
                        
                        barricade_collision = 0;
                        // figure out if the home missile collided with a barricade block 
                        if ( (home_missile_y >= BARRICADE1_V_COORD) && 
                        (home_missile_x >= BARRICADE1_H_COORD) && 
                        (home_missile_x < BARRICADE1_H_COORD+BARRICADE_WIDTH) &&
                        (home_missile_y <= 400)) 
                        {
                            // change 
                            barricade_col_id = (int)((home_missile_x - BARRICADE1_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                            if ( last_barricade_block[0][barricade_col_id] > 0 ) 
                            { 
                                barricade_block_idx = (last_barricade_block[0][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                             
                                                            
                                IOWR_VGA_DATA(VGA_BASE,(3<<14)|barricade_block_idx,0);
                                
                                if (( last_barricade_block[0][barricade_col_id] == 1 ) 
                                || ( last_barricade_block[0][barricade_col_id] == first_barricade_block[0][barricade_col_id] ) )
                                {
                                    last_barricade_block[0][barricade_col_id] = 0; 
                                } 
                                else { 
                                    last_barricade_block[0][barricade_col_id] = last_barricade_block[0][barricade_col_id]-1;
                                }
                                
                              
                                
                                home_missile_y = 0; 
                                home_missile_x = 0;
                                barricade_collision = 1;
                            }
                        }
                        
             
                        
                        if ( (home_missile_y >= BARRICADE2_V_COORD) && 
                        (home_missile_x >= BARRICADE2_H_COORD) && 
                        (home_missile_x < BARRICADE2_H_COORD+BARRICADE_WIDTH) &&
                        (home_missile_y <= 400)) 
                        {
                            barricade_col_id = (int)((home_missile_x - BARRICADE2_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                            if ( last_barricade_block[1][barricade_col_id] > 0 ) 
                            { 
                               barricade_block_idx = (last_barricade_block[1][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                             
                                                            
                                IOWR_VGA_DATA(VGA_BASE,(3<<14)|(1<<6)|barricade_block_idx,0);
                                
                                if (( last_barricade_block[1][barricade_col_id] == 1 ) 
                                || ( last_barricade_block[1][barricade_col_id] == first_barricade_block[1][barricade_col_id] ) )
                                {
                                    last_barricade_block[1][barricade_col_id] = 0; 
                                } 
                                else { 
                                    last_barricade_block[1][barricade_col_id] = last_barricade_block[1][barricade_col_id]-1;
                                }
                                
                                
                                home_missile_y = 0; 
                                home_missile_x = 0;
                                barricade_collision = 1;
                            }
                        }
                        
           
                        if ( (home_missile_y >= BARRICADE3_V_COORD) && 
                        (home_missile_x >= BARRICADE3_H_COORD) && 
                        (home_missile_x < BARRICADE3_H_COORD+BARRICADE_WIDTH) &&
                        (home_missile_y <= 400)) 
                        {
                            barricade_col_id = (int)((home_missile_x - BARRICADE3_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                            if ( last_barricade_block[2][barricade_col_id] > 0 ) 
                            { 
                               barricade_block_idx = (last_barricade_block[2][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                             
                                                            
                                IOWR_VGA_DATA(VGA_BASE,(3<<14)|(2<<6)|barricade_block_idx,0);
                                
                                if (( last_barricade_block[2][barricade_col_id] == 1 ) 
                                || ( last_barricade_block[2][barricade_col_id] == first_barricade_block[2][barricade_col_id] ) )
                                {
                                    last_barricade_block[2][barricade_col_id] = 0; 
                                } 
                                else { 
                                    last_barricade_block[2][barricade_col_id] = last_barricade_block[2][barricade_col_id]-1;
                                }
                                home_missile_y = 0; 
                                home_missile_x = 0;
                                barricade_collision = 1;
                            }
                        }
                        
                 
                        
                        if ( (home_missile_y >= BARRICADE4_V_COORD) && 
                        (home_missile_x >= BARRICADE4_H_COORD) && 
                        (home_missile_x < BARRICADE4_H_COORD+BARRICADE_WIDTH) &&
                        (home_missile_y <= 400)) 
                        {
                            barricade_col_id = (int)((home_missile_x - BARRICADE4_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                            if ( last_barricade_block[3][barricade_col_id] > 0 ) 
                            { 
                               barricade_block_idx = (last_barricade_block[3][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                             
                                                            
                                IOWR_VGA_DATA(VGA_BASE,(3<<14)|(3<<6)|barricade_block_idx,3);
                                
                                if (( last_barricade_block[3][barricade_col_id] == 1 ) 
                                || ( last_barricade_block[3][barricade_col_id] == first_barricade_block[3][barricade_col_id] ) )
                                {
                                    last_barricade_block[3][barricade_col_id] = 0; 
                                } 
                                else { 
                                    last_barricade_block[3][barricade_col_id] = last_barricade_block[3][barricade_col_id]-1;
                                }
                                home_missile_y = 0; 
                                home_missile_x = 0;
                                barricade_collision = 1;                         
                            }
                        }
                       
                     
                        // home missile barricade collision
                        if(barricade_collision==1 && game_state==2)
                        {
                            ////////////produce sound////////////////
                        IOWR_32DIRECT(AUDIO_BASE,0,0x111100FF);
                        ddelay = 6;
//                         while(ddelay!=0)
//                          {
//                            ddelay--;
//                          }
//                        IOWR_32DIRECT(AUDIO_BASE,0,0x000000FF);
                        /////////////////////////////////////////
                        }
                       
                
                        // change 
                        if ( !barricade_collision ) { 
                            rowId = NUM_ROWS; 
                            
                            if (( home_missile_x >= wave_h ) &&
                             ( ( (home_missile_x - wave_h) % (ALIEN_WIDTH + ALIEN_GAP)) < ALIEN_WIDTH ))
                            {
                                // find the col index of the alien 
                                colIdx =    (int) ((home_missile_x - wave_h) / (ALIEN_WIDTH + ALIEN_GAP));  
                                
                                if ((colIdx < NUM_ALIENS_PER_ROW) && ( first_alien_incol[colIdx] > 0) && 
                                 ( home_missile_y < (wave_v + ALIEN_LENGTH + 
                                 ( first_alien_incol[colIdx] - 1) *  (ALIEN_LENGTH + ALIEN_GAP))))
                                {
                                    // at least one invader belongs to us 
                                    rowIdx = first_alien_incol[colIdx]; 
                                    first_alien_incol[colIdx] = first_alien_incol[colIdx] - 1;
                                    
                                    if ( !first_alien_incol[colIdx] ) 
                                    {
                                     num_active_cols--;   
                                    }  
                                    
                                    // convert 2D index to 1D 
                                    alienIdx = (rowIdx - 1) * NUM_ALIENS_PER_ROW + colIdx;
                                    
//                                    printf("rowIdx = %d", colIdx );
//                                     printf("colIdx = %d", colIdx );
//                                    printf("alienIdx = %d", alienIdx );
//                                    printf("remainder = %d\n", (home_missile_x - wave_h) % (ALIEN_WIDTH + ALIEN_GAP));
                                    
                                    // deliver the good news to the hardware
                                    IOWR_VGA_DATA(VGA_BASE,(1<<15)|alienIdx,wave_v);
                                    
                                    // The 3 Billion Dollar home missile perished in the collision. 
                                    // Cease its existence.   
                                    home_missile_y = 0;
                                    home_missile_x = 0;
                                    // update score and send to the hardware
                                    current_score+=10;
                                    display_score = current_score;
                                    //IOWR_VGA_DATA(VGA_BASE, 7, current_score%10)
                                    display_score/=10;
                                    IOWR_VGA_DATA(VGA_BASE, 6, display_score%10);
                                    display_score/=10;
                                    IOWR_VGA_DATA(VGA_BASE, 5, display_score%10);
                                    display_score/=10;
                                    IOWR_VGA_DATA(VGA_BASE, 4, display_score%10);
                                    display_score/=10;
                                    IOWR_VGA_DATA(VGA_BASE, 3, display_score%10);
                                    
                                    ////////////produce sound////////////////
                                    IOWR_32DIRECT(AUDIO_BASE,0,0x111100AA);
                                   
                                    cdelay=6;
                                    
                                   
                                    
                                    
                                    
                                    /////////////////////////////////////////
                                }
                            }   
                        }
                        
                     
                    }  
                    IOWR_VGA_DATA(VGA_BASE, 9, home_missile_x);
                    IOWR_VGA_DATA(VGA_BASE, 10, home_missile_y);
                }
                
                  if ( cdelay > 1 ) 
                        {
                            cdelay--; 
                        }
                  else if ( cdelay == 1 ) 
                        {
                         cdelay = 0; 
                         IOWR_32DIRECT(AUDIO_BASE,0,0x00000069);
                            
                        }
                
                  if ( ddelay > 1 ) 
                        {
                            ddelay--; 
                        }
                  else if ( ddelay == 1 ) 
                        {
                         ddelay = 0; 
                         IOWR_32DIRECT(AUDIO_BASE,0,0x00000069);
                            
                        }
                
          
                
//                if ( alien_delay_counter < alien_clock_factor-1 )
//                {
//                    alien_delay_counter++; 
//                }
//                else {
                    alien_delay_counter = 0;  
                     // logic for alien waves 
                    direction = alien_phalanx(direction);
               
                    m_idx = 0;
                    while ( m_idx < max_active_missiles ) //alien attacks
                    {   
                        if ( active_missiles[m_idx] ) 
                        { 
                            alien_missile_y[m_idx] =  alien_missile_y[m_idx] + alien_missile_inc;
                            if ( alien_missile_y[m_idx] > ALIEN_MISSILE_BOUNDARY ) 
                            {
                             active_missiles[m_idx] = 0; 
                             alien_missile_x[m_idx] = 0; 
                             alien_missile_y[m_idx] = 0;
                             num_active_missiles--;  
                             IOWR_VGA_DATA(VGA_BASE, (1<<4) | m_idx , 0);
                             IOWR_VGA_DATA(VGA_BASE, (1<<5) | m_idx , 0);                     
                            }
                            else
                            {         
                               IOWR_VGA_DATA(VGA_BASE, (1<<5) | m_idx , alien_missile_y[m_idx]);
                            }
                            
                            barricade_collision = 0;
                            
                            
                            
                            for ( int kk =0; kk < 4 ; kk++ ) 
                            { 
                             //figure out if the alien missile collided with a barricade block 
                            if ( (alien_missile_y[m_idx] >= BARRICADE1_V_COORD-16) && 
                            (alien_missile_x[m_idx] >= BARRICADE1_H_COORD) && 
                            (alien_missile_x[m_idx] < BARRICADE1_H_COORD+BARRICADE_WIDTH)) 
                            {
                                // change 
                                barricade_col_id = (int)((alien_missile_x[m_idx] - BARRICADE1_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                                if ( first_barricade_block[0][barricade_col_id] > 0 ) 
                                { 
                                    barricade_block_idx = (first_barricade_block[0][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                 
                                    IOWR_VGA_DATA(VGA_BASE,(3<<14)|barricade_block_idx,0);
                                    if (( first_barricade_block[0][barricade_col_id] == 16 ) 
                                    || ( first_barricade_block[0][barricade_col_id] == last_barricade_block[0][barricade_col_id] ) )
                                    {
                                        first_barricade_block[0][barricade_col_id] = 0; 
                                    } 
                                    else { 
                                        first_barricade_block[0][barricade_col_id] = first_barricade_block[0][barricade_col_id]+1;
                                    }
                                    alien_missile_y[m_idx] = 0; 
                                    alien_missile_x[m_idx] = 0;
                                    active_missiles[m_idx] = 0;
                                    num_active_missiles--;
                                    barricade_collision = 1;
                                    }
                                // change 
                                
                                
                                }
                            }
                            if ( (alien_missile_y[m_idx] >= BARRICADE2_V_COORD-16) && 
                            (alien_missile_x[m_idx] >= BARRICADE2_H_COORD) && 
                            (alien_missile_x[m_idx] < BARRICADE2_H_COORD+BARRICADE_WIDTH)) 
                            {
                                barricade_col_id = (int)((alien_missile_x[m_idx] - BARRICADE2_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                                if ( last_barricade_block[1][barricade_col_id] > 0 ) 
                                { 
                                    barricade_block_idx = (first_barricade_block[1][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                 
                                    IOWR_VGA_DATA(VGA_BASE,(3<<14)|(1<<6)|barricade_block_idx,1);
                                    if (( first_barricade_block[1][barricade_col_id] == 16 ) 
                                    || ( first_barricade_block[1][barricade_col_id] == last_barricade_block[1][barricade_col_id] ) )
                                    {
                                        first_barricade_block[1][barricade_col_id] = 0; 
                                    } 
                                    else { 
                                        first_barricade_block[1][barricade_col_id] = first_barricade_block[1][barricade_col_id]+1;
                                    }
                                    alien_missile_y[m_idx] = 0; 
                                    alien_missile_x[m_idx] = 0;
                                    active_missiles[m_idx] = 0;
                                    num_active_missiles--;
                                    barricade_collision = 1;
                                }
                            }
                            if ( (alien_missile_y[m_idx] >= BARRICADE3_V_COORD-16) && 
                            (alien_missile_x[m_idx] >= BARRICADE3_H_COORD) && 
                            (alien_missile_x[m_idx] < BARRICADE3_H_COORD+BARRICADE_WIDTH)) 
                            {
                                barricade_col_id = (int)((alien_missile_x[m_idx] - BARRICADE3_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                                if ( last_barricade_block[2][barricade_col_id] > 0 ) 
                                { 
                                     barricade_block_idx = (first_barricade_block[2][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                 
                                    IOWR_VGA_DATA(VGA_BASE,(3<<14)|(2<<6)|barricade_block_idx,2);
                                    if (( first_barricade_block[2][barricade_col_id] == 16 ) 
                                    || ( first_barricade_block[2][barricade_col_id] == last_barricade_block[2][barricade_col_id] ) )
                                    {
                                        first_barricade_block[2][barricade_col_id] = 0; 
                                    } 
                                    else { 
                                        first_barricade_block[2][barricade_col_id] = first_barricade_block[2][barricade_col_id]+1;
                                    }
                                    alien_missile_y[m_idx] = 0; 
                                    alien_missile_x[m_idx] = 0;
                                    active_missiles[m_idx] = 0;
                                    num_active_missiles--;
                                    barricade_collision = 1;
                                }
                            }
                            if ( (alien_missile_y[m_idx] >= BARRICADE4_V_COORD-16) && 
                            (alien_missile_x[m_idx] >= BARRICADE4_H_COORD) && 
                            (alien_missile_x[m_idx] < BARRICADE4_H_COORD+BARRICADE_WIDTH)) 
                            {
                                barricade_col_id = (int)((alien_missile_x[m_idx] - BARRICADE4_H_COORD)/BARRICADE_BLOCK_WIDTH); 
                                if ( last_barricade_block[3][barricade_col_id] > 0 ) 
                                { 
                                    barricade_block_idx = (first_barricade_block[3][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                 
                                    IOWR_VGA_DATA(VGA_BASE,(3<<14)|(3<<6)|barricade_block_idx,3);
                                    if (( first_barricade_block[3][barricade_col_id] == 16 ) 
                                    || ( first_barricade_block[3][barricade_col_id] == last_barricade_block[3][barricade_col_id] ) )
                                    {
                                        first_barricade_block[3][barricade_col_id] = 0; 
                                    } 
                                    else { 
                                        first_barricade_block[3][barricade_col_id] = first_barricade_block[3][barricade_col_id]+1;
                                    }
                                    alien_missile_y[m_idx] = 0; 
                                    alien_missile_x[m_idx] = 0;
                                    active_missiles[m_idx] = 0;
                                    num_active_missiles--;
                                    barricade_collision = 1;
                                }
                            }
                            // change 
                            
                             //  missile barricade collision
                                int edelay=20000;
                        // home missile barricade collision
                        if(barricade_collision==1 && game_state==2)
                        {
                            ////////////produce sound////////////////
//                            IOWR_32DIRECT(AUDIO_BASE,0,0x111100FF);
//                             while(edelay!=0)
//                            {
//                                edelay--;
//                            }
//                            IOWR_32DIRECT(AUDIO_BASE,0,0x000000FF);
                            /////////////////////////////////////////
                        }
                            
                            if(!barricade_collision){ // change 
                            // killing our home ship
                             if  (alien_missile_y[m_idx] >= ALIEN_MISSILE_BOUNDARY - alien_missile_inc && 
                                     alien_missile_x[m_idx] >= val && alien_missile_x[m_idx] <=val+32)
                              {                        
                                IOWR_VGA_DATA(VGA_BASE, 0x000B, 0);
                                lives1--;
                                IOWR_VGA_DATA(VGA_BASE, 8, lives1);
                  
                                
                                
                                int i;
                                for (i = 0  ; i < MAX_MISSILES; i++ ) 
                                {
                                    active_missiles[i] = 0;
                                    alien_missile_x[i] = 0; 
                                    alien_missile_y[i] = 0;
                                }
                                num_active_missiles=0;
                                state_reset = 1;
                                IOWR_8DIRECT(PS2_BASE,0,0);
                                delay(1000000);
                                IOWR_VGA_DATA(VGA_BASE, 0x000B, 1 );                           
                               }
                            }// change 
                        }
                        m_idx++;
                }
    
                //Reading Keyboard Inputs 
                if (IORD_8DIRECT(PS2_BASE,0))
                {  
                    state=read_key();          
                }  
    
    
                if ( num_active_missiles < max_active_missiles ) //
                {
                        if ( !num_active_cols ) 
                        {
                         printf("End of level flag set 2\n");
                        end_of_level_flag = 1; 
//                        if (wave_delay > 1000 ) 
//                            wave_delay -= WAVE_DELAY_DEC;
//                        if(max_active_missiles<MAX_MISSILES)
//                            max_active_missiles++;
                            
                           delay(900000);
                          
                        } 
                        else { 
                            // find the free slot
                             m_idx = 0; 
                            while ( active_missiles[m_idx] ) { 
                                  m_idx++;    
                             }                
                            active_missiles[m_idx] = 1;
                             num_active_missiles++;
    
                            // pick an alien column in random 
                            do { 
                              randCol = ( rand() % NUM_ALIENS_PER_ROW ) ; 
                            } while ( ! first_alien_incol[randCol] ) ;
                    
                            // pick an alien row in random 
                            randRow = rand() % first_alien_incol[randCol];   
                    
                             // figure out the missile origin 
                             alien_missile_x[m_idx] = wave_h + (randCol) * (ALIEN_WIDTH + ALIEN_GAP) + (ALIEN_WIDTH /2); 
                             alien_missile_y[m_idx] = wave_v + (randRow) * (ALIEN_LENGTH + ALIEN_GAP) + ALIEN_LENGTH;    
                    
                            IOWR_VGA_DATA(VGA_BASE, (1<<4) | m_idx , alien_missile_x[m_idx]);
                            IOWR_VGA_DATA(VGA_BASE, (1<<5) | m_idx , alien_missile_y[m_idx]);
                        }
                   }
               // }
               counter = 0; // reset counter
               
               //printf("end \n");
            }
            else{
                counter++;
            }
            
            //Reading Keyboard Inputs 
            if (IORD_8DIRECT(PS2_BASE,0))
            {  
                state=read_key();          
            }
            
            if(!key_delay)
            {
                response(state);
                key_delay=5000;
            }
            else
                key_delay--;  
           
            if (state_reset)
            {
                state='I';
                state_reset = 0;
            }                                                  
        }
          //change game state to 'game over screen'//
          game_state=3;
          IOWR_VGA_DATA(VGA_BASE,52 , game_state);
          ////////////////////////////////////// 
         // delay(900000);
          //wait for another round of game 
            while (!IORD_8DIRECT(PS2_BASE,0));
                code=IORD_8DIRECT(PS2_BASE,4);
            while (!IORD_8DIRECT(PS2_BASE,0));
                code= IORD_8DIRECT(PS2_BASE,4);
            while (!IORD_8DIRECT(PS2_BASE,0));
                code= IORD_8DIRECT(PS2_BASE,4);
          
          //////////////////////////////////////                   
        
         IOWR_VGA_DATA(VGA_BASE, 0xFFFF, 0);
                //new_level();
                ent_count++;
                restart = 1;

    }while(1);
    printf("should never exit\n");
    
    return 0;
}



