

////*
// * 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 4

#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]; 


int first_barricade_block[4][NUM_H_BLOCKS_BARRICADE];  
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; 
    
    
    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;
     
    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
    {

        
        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);
        //////////////////////////////////////
        
       

         
        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)
            {
             
                int nn = 0;
                int breachFlag = 0; 
                for ( nn = 0; nn < NUM_ALIENS_PER_ROW; nn++ ) 
                {

                 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 
                        int kk =0;
                        for ( kk =0; kk < 4; kk++ ) 
                        { 
                            if ( (home_missile_y >= barricade_v_coords[kk]) && 
                            (home_missile_x >= barricade_h_coords[kk]) && 
                            (home_missile_x < barricade_h_coords[kk]+BARRICADE_WIDTH) &&
                            (home_missile_y <= 400)) 
                            {
                                // change 
                                barricade_col_id = (int)((home_missile_x - barricade_h_coords[kk])/BARRICADE_BLOCK_WIDTH); 
                                if ( last_barricade_block[kk][barricade_col_id] > 0 ) 
                                { 
                                    barricade_block_idx = (last_barricade_block[kk][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                 
                                                                
                                    IOWR_VGA_DATA(VGA_BASE,(3<<14)|(kk<<6)|barricade_block_idx,0);
                                    
                                    if (( last_barricade_block[kk][barricade_col_id] == 1 ) 
                                    || ( last_barricade_block[kk][barricade_col_id] == first_barricade_block[kk][barricade_col_id] ) )
                                    {
                                        first_barricade_block[kk][barricade_col_id] = 0; 
                                        last_barricade_block[kk][barricade_col_id] = 0; 
                                    } 
                                    else { 
                                        last_barricade_block[kk][barricade_col_id] = last_barricade_block[kk][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;

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

                    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;
                            
                            
                            int kk = 0;
                            for ( kk =0; kk < 4 ; kk++ ) 
                            { 
                                 //figure out if the alien missile collided with a barricade block 
                                if ( (alien_missile_y[m_idx] >= barricade_v_coords[kk]-16) && 
                                (alien_missile_x[m_idx] >= barricade_h_coords[kk]) && 
                                (alien_missile_x[m_idx] < barricade_h_coords[kk]+BARRICADE_WIDTH)) 
                                {
                                 
                                    barricade_col_id = (int)((alien_missile_x[m_idx] - barricade_h_coords[kk])/BARRICADE_BLOCK_WIDTH); 
                                    if ( first_barricade_block[kk][barricade_col_id] > 0 ) 
                                    { 
                                        barricade_block_idx = (first_barricade_block[kk][barricade_col_id]-1) * NUM_H_BLOCKS_BARRICADE + barricade_col_id;     
                                     
                                        IOWR_VGA_DATA(VGA_BASE,(3<<14)|(kk<<6)|barricade_block_idx,0);
                                        if (( first_barricade_block[kk][barricade_col_id] == 16 ) 
                                        || ( first_barricade_block[kk][barricade_col_id] == last_barricade_block[kk][barricade_col_id] ) )
                                        {
                                            first_barricade_block[kk][barricade_col_id] = 0; 
                                            last_barricade_block[kk][barricade_col_id] = 0;
                                        } 
                                        else { 
                                            first_barricade_block[kk][barricade_col_id] = first_barricade_block[kk][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;
                                        }
                                   
                                    
                                    
                                }
                            }

                            
                             //  missile barricade collision
                                int edelay=20000;
     
                            
                            if(!barricade_collision){  
                            // 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 );                           
                               }
                            }
                        }
                        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; 

                            
                           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 alive alien in the column 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
               
             
            }
            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);
          ////////////////////////////////////// 
   
          //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);
                ent_count++;
                restart = 1;

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



