#include <allegro.h>
#include <iostream>
#include <stdlib.h>

#define TAM_2 0
#define TAM_3 1
#define TAM_4 2

#define IA_NORMAL 1
#define IA_INIT 0
#define IA_BUSCA_ORIENTACION 2
#define IA_DESTRUYE_BARCO 3

struct{
    char tablero[10][10];
    char disparos[10][10];
    char turno;
    char puntaje;
}typedef JUGADOR;

struct{
    int x;
    int y;
    int x_dist;
    int y_dist;
    int x_fase;
    int y_fase;
    char dir;
    bool orient;
    char estado;
}typedef IA;

int fijar(JUGADOR &jug,int tipo,int x,int y,int dir);
void cargar_sprites();
void jugar(JUGADOR &jug_ac,JUGADOR &jug_pa,bool modo/*1=auto*/);
void ubicar_barcos(JUGADOR &jug,bool modo /*1=auto*/);
void mostrar_disparos(JUGADOR jug);
void mostrar_barcos(JUGADOR jug);
void mostrar_agua(int turno);

BITMAP* ship2_1;
BITMAP* ship2_1_r;
BITMAP* ship2_2;
BITMAP* ship2_2_r;
BITMAP* ship3_2;
BITMAP* ship3_2_r;
BITMAP* sea;
BITMAP* water;
BITMAP* hit;
BITMAP* target;
BITMAP* img_buffer;
BITMAP* xpace_logo;

SAMPLE* snd_disparo;
SAMPLE* snd_agua;
int pan = 128;
int pitch = 1000;

IA XFAI;
int main(){
    bool terminar=0;
    srand(time(NULL));
    JUGADOR humano;
    JUGADOR compu;
    XFAI.estado=IA_INIT;
    compu.puntaje=0;
    humano.puntaje=0;
    
    for(int i=0;i<10;i++)
        for(int j=0;j<10;j++){
            humano.tablero[i][j]=0;
            humano.disparos[i][j]=0;
            compu.tablero[i][j]=0;
            compu.disparos[i][j]=0;
        }
    compu.turno=1;
    humano.turno=2;

    if(allegro_init()!=0){
        //mensaje de error
        return 1;
    }
    set_color_depth(16);
    set_color_conversion(COLORCONV_TOTAL|COLORCONV_KEEP_TRANS);

    if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 320, 0, 0)!=0){
        //mensaje de error
        return 1;
    }
    if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) != 0) {
       allegro_message("Error initialising sound system\n%s\n", allegro_error);
       return 1;
    }
    snd_agua=load_sample("agua.wav");
    snd_disparo=load_sample("disparo.wav");
    
    install_timer();
    install_mouse();
    install_keyboard();
    
    cargar_sprites();
    
    draw_sprite(screen,xpace_logo,0,10);
    poll_mouse();
    while(!mouse_b&1)poll_mouse();
    img_buffer=create_bitmap(32,32);
    clear_bitmap(img_buffer);
    rectfill(screen,SCREEN_W/4,SCREEN_H/4+20,(SCREEN_W/4)*3,(SCREEN_H/4)*3-20,makecol(40,0,220));
    rect(screen,SCREEN_W/2-50,170,SCREEN_W/2-10,185,makecol(255,255,255));
    rect(screen,SCREEN_W/2+50,170,SCREEN_W/2+10,185,makecol(255,255,255));
    textprintf_centre_ex(screen,font,SCREEN_W/2,150,makecol(255,255,255),makecol(40,0,220),"Colocar barcos manualmente?");
    textprintf_centre_ex(screen,font,SCREEN_W/2-30,175,makecol(255,255,255),makecol(40,0,220),"Si");
    textprintf_centre_ex(screen,font,SCREEN_W/2+30,175,makecol(255,255,255),makecol(40,0,220),"No");
    show_mouse(screen);
    while(terminar==0){
        poll_mouse();
        if(mouse_b&1){
            if(mouse_x>SCREEN_W/2-50 && mouse_y>170
               && mouse_x<SCREEN_W/2-10 && mouse_y<185){
                show_mouse(NULL);
                rectfill(screen,SCREEN_W/2-50,170,SCREEN_W/2-10,185,makecol(255,255,255));
                terminar=1;
                while(mouse_b&1)poll_mouse();
                ubicar_barcos(humano,0);
            }
            if(mouse_x<SCREEN_W/2+50 && mouse_y>170
               && mouse_x>SCREEN_W/2+10 && mouse_y<185){
                show_mouse(NULL);
                rectfill(screen,SCREEN_W/2+50,170,SCREEN_W/2+10,185,makecol(255,255,255));
                terminar=1;
                while(mouse_b&1)poll_mouse();
                ubicar_barcos(humano,1);
            }
        }//end if
    }//end while
    ubicar_barcos(compu,1);
    
    clear_to_color(screen,makecol(255,0,0));
    
    mostrar_agua(humano.turno);
    mostrar_barcos(humano);
    mostrar_agua(compu.turno);
    
    while(humano.puntaje!=14 && compu.puntaje!=14){
        jugar(humano,compu,0);
        mostrar_agua(compu.turno);
        mostrar_disparos(compu);

        jugar(compu,humano,1);
        mostrar_agua(humano.turno);
        mostrar_barcos(humano);
        mostrar_disparos(humano);
    }

    mostrar_agua(humano.turno);
    mostrar_agua(compu.turno);
    mostrar_barcos(humano);
    mostrar_barcos(compu);
    mostrar_disparos(humano);
    mostrar_disparos(compu);
    
    while(mouse_b&1)poll_mouse();
    while(!mouse_b&1)poll_mouse();
    
    rectfill(screen,SCREEN_W/4,SCREEN_H/4+20,(SCREEN_W/4)*3,(SCREEN_H/4)*3-20,makecol(40,0,220));
    rect(screen,SCREEN_W/2-50,170,SCREEN_W/2+50,185,makecol(255,255,255));
    if(humano.puntaje==14){
        textprintf_centre_ex(screen,font,SCREEN_W/2,150,makecol(255,255,255),makecol(40,0,220),"Has Ganado ^_^");
    }else{
        textprintf_centre_ex(screen,font,SCREEN_W/2,150,makecol(255,255,255),makecol(40,0,220),"Has Perdido t_t");
    }
    textprintf_centre_ex(screen,font,SCREEN_W/2,175,makecol(255,255,255),makecol(40,0,220),"Aceptar");
    show_mouse(screen);
    terminar=0;
    while(terminar==0){
        poll_mouse();
        if(mouse_b&1){
            if(mouse_x>SCREEN_W/2-50 && mouse_y>170
               && mouse_x<SCREEN_W/2+50 && mouse_y<185){
                show_mouse(NULL);
                rectfill(screen,SCREEN_W/2-50,170,SCREEN_W/2+50,185,makecol(255,255,255));
                terminar=1;
            }
        }//end if
    }//end while
    while(mouse_b&1)poll_mouse();

}
END_OF_MAIN();

void cargar_sprites(){
    ship2_1=load_bitmap("ship2-1.tga",NULL);
    ship2_1_r=load_bitmap("ship2-1-r.TGA",NULL);
    ship2_2=load_bitmap("ship2-2.TGA",NULL);
    ship2_2_r=load_bitmap("ship2-2-r.TGA",NULL);
    ship3_2=load_bitmap("ship3-2.TGA",NULL);
    ship3_2_r=load_bitmap("ship3-2-r.TGA",NULL);
    sea=load_bitmap("sea.TGA",NULL);
    water=load_bitmap("water.TGA",NULL);
    hit=load_bitmap("hit.TGA",NULL);
    target=load_bitmap("target.TGA",NULL);
    xpace_logo=load_bitmap("xpace.TGA",NULL);
}

void jugar(JUGADOR &jug_ac,JUGADOR &jug_pa,bool modo/*1=auto*/){
    int x,y,aum=0,cont=0;
    bool terminar=0;
    if(modo==0){
        int x_tab=0,x,y;
        if(jug_pa.turno==2)x_tab=320;
        while(terminar==0){
            poll_mouse();
            x=(mouse_x-x_tab)/32;
            y=(mouse_y)/32;
            if(x>9)x=9;if(y>9)y=9;
            if(x<0)x=0;if(y<0)y=0;
            if(mouse_b&1){
                if(jug_pa.disparos[x][y]==0){
                    if(jug_pa.tablero[x][y]!=0){
                        jug_pa.disparos[x][y]=2;
                        jug_ac.puntaje++;

                        stop_sample(snd_agua);
                        play_sample(snd_disparo, 255, pan, pitch, FALSE);
                    }else{
                        jug_pa.disparos[x][y]=1;

                        stop_sample(snd_agua);
                        play_sample(snd_agua, 255, pan, pitch, FALSE);
                    }
                    terminar=1;
                }
                while(mouse_b&1)poll_mouse();
            }
            acquire_screen();
            mostrar_agua(jug_pa.turno);
            mostrar_disparos(jug_pa);
            draw_sprite(screen,target,x_tab+x*32,y*32);
            release_screen();
        }//end while
    }else{
        do{
            cont=0;terminar=0;
            switch(XFAI.estado){
                case IA_INIT:
                    XFAI.x_dist=2+rand()%3;
                    XFAI.x_fase=rand()%XFAI.x_dist;
                    XFAI.y_dist=2+rand()%3;
                    XFAI.y_fase=rand()%XFAI.y_dist;
                    XFAI.estado=IA_NORMAL;
                case IA_NORMAL:
                    while(terminar==0){
                        cont++;
                        x=(rand()%(10/XFAI.x_dist))*XFAI.x_dist+XFAI.x_fase;
                        y=(rand()%(10/XFAI.y_dist))*XFAI.y_dist+XFAI.y_fase;
                        if(jug_pa.disparos[x][y]==0){
                            if(jug_pa.tablero[x][y]!=0){
                                jug_pa.disparos[x][y]=2;
                                jug_ac.puntaje++;
                                XFAI.estado=IA_BUSCA_ORIENTACION;
                                XFAI.x=x;
                                XFAI.y=y;
        
                                stop_sample(snd_agua);
                                play_sample(snd_disparo, 255, pan, pitch, FALSE);
                            }else{
                                jug_pa.disparos[x][y]=1;
        
                                stop_sample(snd_agua);
                                play_sample(snd_agua, 255, pan, pitch, FALSE);
                            }
                            terminar=1;
                            cont=0;
                        }
                        if(cont==1000){
                            XFAI.estado=IA_INIT;
                            terminar=1;
                        }
                    }
                    break;
                case IA_BUSCA_ORIENTACION:
                    while(terminar==0){
                        XFAI.orient=rand()%2;
                        if(XFAI.orient==0){
                            if(rand()%2)x=XFAI.x+1;else x=XFAI.x-1;
                            y=XFAI.y;
                        }else{
                            if(rand()%2)y=XFAI.y+1;else y=XFAI.y-1;
                            x=XFAI.x;
                        }
                        if(jug_pa.disparos[x][y]==0){
                            if(jug_pa.tablero[x][y]!=0){
                                jug_pa.disparos[x][y]=2;
                                jug_ac.puntaje++;
                                XFAI.estado=IA_DESTRUYE_BARCO;
                                XFAI.dir=0;
        
                                stop_sample(snd_agua);
                                play_sample(snd_disparo, 255, pan, pitch, FALSE);
                            }else{
                                jug_pa.disparos[x][y]=1;
        
                                stop_sample(snd_agua);
                                play_sample(snd_agua, 255, pan, pitch, FALSE);
                            }
                            terminar=1;
                            cont=0;
                        }
                    }//end while
                    break;
                case IA_DESTRUYE_BARCO:
                    while(terminar==0){
                        if(XFAI.orient==0){
                            if(XFAI.dir==0)XFAI.dir=1+rand()%2;
                            if(XFAI.dir==1)x=XFAI.x-aum;else x=XFAI.x+aum;
                            y=XFAI.y;
                        }else{
                            if(XFAI.dir==0)XFAI.dir=1+rand()%2;
                            if(XFAI.dir==1)y=XFAI.y-aum;else y=XFAI.y+aum;
                            x=XFAI.x;
                        }//end else
                        if(jug_pa.disparos[x][y]==0){
                            if(jug_pa.tablero[x][y]!=0){
                                jug_pa.disparos[x][y]=2;
                                jug_ac.puntaje++;
                                XFAI.estado=IA_DESTRUYE_BARCO;
                                XFAI.dir=0;
        
                                stop_sample(snd_agua);
                                play_sample(snd_disparo, 255, pan, pitch, FALSE);
                            }else{
                                jug_pa.disparos[x][y]=1;
        
                                stop_sample(snd_agua);
                                play_sample(snd_agua, 255, pan, pitch, FALSE);
                            }
                            terminar=1;
                            cont=0;
                        }else{
                            if(jug_pa.disparos[x][y]==1){
                                if(cont==1){
                                    XFAI.estado=IA_NORMAL;
                                    terminar=1;
                                }
                                if(XFAI.dir==1)XFAI.dir=2;else XFAI.dir=1;
                                cont=1;
                                aum=1;
                            }else aum++;
                        }
                    }//end while
                    break;
            }//end switch
        }while(cont!=0);
    }//end else

}

void ubicar_barcos(JUGADOR &jug,bool modo /*1=auto*/){
    if(modo==0){
        int x_tab=0,x,y,barco=1,tipo=TAM_4,tam=128;
        bool dir=0;
        if(jug.turno==2)x_tab=320;
        BITMAP* img_barco;
        BITMAP* tmp_barco;
        tmp_barco=create_bitmap(128,128);
        img_barco=create_bitmap(128,32);
        draw_sprite(img_barco,ship2_2_r,0,0);
        draw_sprite(img_barco,ship3_2_r,32,0);
        draw_sprite(img_barco,ship3_2_r,64,0);
        draw_sprite(img_barco,ship2_1_r,96,0);

        do{
            poll_mouse();
            x=(mouse_x-x_tab)/32;
            y=(mouse_y)/32;
            if(x>9)x=9;if(y>9)y=9;
            if(x<0)x=0;if(y<0)y=0;
            if(mouse_b&1 && fijar(jug,tipo,x,y,dir)==0){
                switch(barco){
                    case 1:
                    case 2:
                        tipo=TAM_3;dir=0;tam=96;
                        img_barco=create_bitmap(96,32);
                        tmp_barco=create_bitmap(96,96);
                        clear_bitmap(img_barco);
                        draw_sprite(img_barco,ship2_2_r,0,0);
                        draw_sprite(img_barco,ship3_2_r,32,0);
                        draw_sprite(img_barco,ship2_1_r,64,0);
                        break;
                    case 3:
                    case 4:
                        tipo=TAM_2;dir=0;tam=64;
                        img_barco=create_bitmap(64,32);
                        tmp_barco=create_bitmap(64,64);
                        clear_bitmap(img_barco);
                        draw_sprite(img_barco,ship2_2_r,0,0);
                        draw_sprite(img_barco,ship2_1_r,32,0);
                        break;
                        
                }//end switch
                barco++;
                while(mouse_b&1)poll_mouse();
            }
            if(mouse_b&2){
                if(dir==0){
                    clear_bitmap(tmp_barco);
                    draw_sprite(tmp_barco,img_barco,0,0);
                    img_barco=create_bitmap(32,tam);
                    rotate_sprite(img_barco,tmp_barco,0,0,itofix(-64));
                    dir=1;
                }else{
                    clear_bitmap(tmp_barco);    
                    draw_sprite(tmp_barco,img_barco,0,0);
                    img_barco=create_bitmap(tam,32);
                    rotate_sprite(img_barco,tmp_barco,0,0,itofix(64));
                    dir=0;
                }
                while(mouse_b&2)poll_mouse();
            }
            acquire_screen();
            mostrar_agua(jug.turno);
            mostrar_barcos(jug);
            draw_sprite(screen,img_barco,x_tab+x*32,y*32);
            release_screen();
        }while(barco<6);
    }else{
            while(fijar(jug,TAM_2,rand()%10,rand()%10,rand()%2)!=0);
            while(fijar(jug,TAM_2,rand()%10,rand()%10,rand()%2)!=0);
            while(fijar(jug,TAM_3,rand()%10,rand()%10,rand()%2)!=0);
            while(fijar(jug,TAM_3,rand()%10,rand()%10,rand()%2)!=0);
            while(fijar(jug,TAM_4,rand()%10,rand()%10,rand()%2)!=0);
    }

}

int fijar(JUGADOR &jug,int tipo,int x,int y,int dir){
    int i,j;
    char barco[3];

    if(dir==0){
        barco[0]='<';
        barco[1]='-';
        barco[2]='>';
        i=1;
        j=0;
    }else{
        i=0;
        j=1;
        barco[0]='^';
        barco[1]='|';
        barco[2]='v';
    }
    switch(tipo){
        case TAM_2:
            if(x>9-i || y>9-j)return 1;
            if(jug.tablero[x][y]!=0 || jug.tablero[x+i][y+j]!=0)return 2;
            jug.tablero[x][y]=barco[0];
            jug.tablero[x+i][y+j]=barco[2];
            break;
        case TAM_3:
            if(x>9-i*2 || y>9-j*2)return 1;
            if(jug.tablero[x][y]!=0 || jug.tablero[x+i][y+j]!=0 || jug.tablero[x+i*2][y+j*2]!=0)return 2;
            jug.tablero[x][y]=barco[0];
            jug.tablero[x+i][y+j]=barco[1];
            jug.tablero[x+i*2][y+j*2]=barco[2];
            break;
        case TAM_4:
            if(x>9-i*3 || y>9-j*3)return 1;
            if(jug.tablero[x][y]!=0 || jug.tablero[x+i][y+j]!=0 || jug.tablero[x+i*2][y+j*2]!=0 || jug.tablero[x+i*3][y+j*3]!=0)return 2;
            jug.tablero[x][y]=barco[0];
            jug.tablero[x+i][y+j]=barco[1];
            jug.tablero[x+i*2][y+j*2]=barco[1];
            jug.tablero[x+i*3][y+j*3]=barco[2];
            break;
    }

    return 0;
}

void mostrar_disparos(JUGADOR jug){
    int x_tab=0;
    if(jug.turno==2)x_tab=320;
    for(int x=0;x<10;x++){
        for(int y=0;y<10;y++){
            switch(jug.disparos[x][y]){
                case 1:
                    draw_sprite(screen,water,x*32+x_tab,y*32);
                    break;
                case 2:
                    draw_sprite(screen,hit,x*32+x_tab,y*32);
                    break;
            }
        }
    }
}

void mostrar_barcos(JUGADOR jug){
    int x_tab=0;
    if(jug.turno==2)x_tab=320;
    for(int x=0;x<10;x++){
        for(int y=0;y<10;y++){
            switch(jug.tablero[x][y]){
                case '^':
                    draw_sprite(screen,ship2_1,x*32+x_tab,y*32);
                    break;
                case '|':
                    draw_sprite(screen,ship3_2,x*32+x_tab,y*32);
                    break;
                case 'v':
                    draw_sprite(screen,ship2_2,x*32+x_tab,y*32);
                    break;
                case '<':
                    draw_sprite(screen,ship2_2_r,x*32+x_tab,y*32);
                    break;
                case '-':
                    draw_sprite(screen,ship3_2_r,x*32+x_tab,y*32);
                    break;
                case '>':
                    draw_sprite(screen,ship2_1_r,x*32+x_tab,y*32);
                    break;
            }
        }
    }
}

void mostrar_agua(int turno){
    int x_tab=0;
    if(turno==2)x_tab=320;
    for(int x=0;x<10;x++){
        for(int y=0;y<10;y++){
            draw_sprite(screen,sea,x*32+x_tab,y*32);
            }
        }
}
