/*
GPL - jqm - ETSI 2013
*/


#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void showMenu(int intro);
void initGame();
void printGame();
void runDemo();
int runInteractive();
void runAuto();

struct square{
    /*casilla base 4x2 chars
     p1p2
     36 O
     casilla Nº 36 tipo Oca
    */
    
    char *player1; //posición coloreada para el jugador 1
    char *player2; //posición coloreada para el jugador 2
    int index;  //numero de casilla
    char *action; /* acción de casilla especial, hardcodeadas según index
                    S = start
                    O = oca {1, 5, 9, 14, 18, 23, 27, 32, 36, 41, 45, 50, 54, 59, 63}
                    P = puente {6, 12}
                    H = hostal/posada {19}
                    D = dados {26, 53}
                    A = agua/pozo {31}
                    L = laberinto {42}
                    C = carcel {52}
                    M = muerte {58}
                    */
};

struct square game[64];

int main(int argc, const char *argv[]){
    
    if((argc > 1) && (argv[1][0] == '-') && (argv[1][1] == 'a')){
        runAuto(); //for num in {1..10}; do sleep 1; ./oca_test -a >>/tmp/stats.txt; done
        return 0;
    }
    
    runInteractive();
    
    printf("\n\n");
    return 0;
    
}

void initGame(){
    
    game[0].player1 = "P1";
    game[0].player2 = "P2";
    game[0].index = 0; 
    game[0].action = "S";
        
    int i;
    
    for(i=1;i<64;i++){
        game[i].player1= "┌─";
        game[i].player2= "─┐";
        game[i].index= i;
        
        if(i==1 || i==5 || i==9 || i==14 || i==18 || i==23 || i==27 || i ==32 || i ==36 || i ==41 || i ==45 || i ==50 || i ==54 || i ==59 || i ==63)
            game[i].action = "_O";
        else if (i==6 || i==12)
            game[i].action = "_P";
        else if (i==19)
            game[i].action = "_H";
        else if (i==26 || i==53)
            game[i].action = "_D";
        else if (i==31)
            game[i].action = "_A";
        else if (i==42)
            game[i].action = "_L";
        else if (i==52)
            game[i].action = "_C";
        else if (i==58)
            game[i].action = "_M";
        else
            game[i].action = "_│";
    }
}

void printGame(){

    void printSquare(int index){
        printf(" %s%s\e[1B\e[4D%2d%s\e[1A",game[index].player1,game[index].player2,game[index].index,game[index].action);
        //1B = 1 linea abajo, 4D = 4 backward, 1A = 1 arriba
    }
    int i;
    printf("\n\n\t\t\t");
    for(i=23; i>14;i--) printSquare(i);
    printf("\n\n\t\t\t");
    printSquare(24); for(i=45; i>38;i--) printSquare(i); printSquare(14);
    printf("\n\n\t\t\t");
    printSquare(25); printSquare(46); for(i=59; i>54;i--) printSquare(i); printSquare(38); printSquare(13);
    printf("\n\n\t\t\t");
    printSquare(26); printSquare(47); for(i=60; i<64;i++) printSquare(i); printSquare(54); printSquare(37); printSquare(12);
    printf("\n\n\t\t\t");
    printSquare(27); for(i=48; i<54;i++) printSquare(i); printSquare(36); printSquare(11);
    printf("\n\n\t\t\t");
    for(i=28; i<36;i++) printSquare(i); printSquare(10);
    printf("\n\n\t\t\t");
    for(i=1; i<10;i++) printSquare(i);
    printf("\n\n\t\t\t");
    
}

void showMenu(int intro){
    
    void typewrite(char *string){
        int i=0;
        srandom (time (0)); //inicializar la seed para random() con el time actual
        struct timespec tim; //tim es una struct del tipo timespec (en time.h) que nanosleep espera como parámetros
        tim.tv_sec = 0;  //0 segundos, se usará tim.tv_nsec + una parte de random
        
        while(string[i]){
        
            tim.tv_nsec = 25000000 + (random()% 100000000); //1/4 segundo serían 250 ms 250000 us 250000000 ns
            
            putchar(string[i]);
            fflush(stdout);
            nanosleep(&tim, NULL);
            i++;
        }
    }
    
    printf("\e[2J\e[5;20H\t\e[4m\e[1mTOCA\e[25m - Como la Oca pero en modo texto!\e[0m\n\n");
    
    printf("\n\t1.- Nueva partida\t\t\t\t4.- Cargar partida\n\t2.- Dados\t\t\t\t\t5.- Guardar partida\n\t3.- Demo\t\t\t\t\t0.- Salir\n\n\n");
    
    if(intro ==1){
        
        game[63].player1 = "\e[1;42m  \e[0m"; //42m = verde
        game[48].player2 = "\e[1;44m  \e[0m"; //44m = azul
        printGame();
        
        typewrite("\n\n\tIntro bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla...");
        
        /*
        typewrite("\n\n\tEl juego de la Toca para 2 personas consiste en avanzar sobre un tablero de casillas mediante el lanzamiento de un dado.\n\tAlgunas de estas casillas tienen un comportamiento especial que te favorece para adelantar como la casilla de oca \n\ty otras te penalizan con turno sín tirar como la de la carcel...\n\n\t... el tablero tiene 63 casillas distribuidas en espiral, deberás llegar a la última con una tirada exacta.\n\tLas casillas especiales llevan una letra indicando la acción: O = oca, P = puente, H = hostal, C = carcel, M = muerte etc...\n\tElige color y suerte con el dado!.\n");
        */
        getchar();
    }

}

void runDemo(){
    //printf("123\n");
    
    int turn=1, index1=1, index2=1, movs1=0, movs2=0, dice ;
    srandom (time (0)); //inicializar la seed para random() con el time actual
    struct timespec turnt; //tim es una struct del tipo timespec (en time.h) que nanosleep espera como parámetros
    turnt.tv_sec = 0;
    turnt.tv_nsec = 250000000;
    
    initGame();
    showMenu(0);
    printGame();
    
    while((game[63].player1 == "┌─") && (game[63].player2 == "─┐")){
        if(turn==1){
            if(index1 > 63) index1 = 63 - (index1 - 63);
            movs1++;
            game[index1].player1 = "\e[1;32m┌─\e[0m";
            
            dice = 1 + (random() % 5);
            index1 = index1 + dice;
            game[index1].player1 = "\e[1;42m  \e[0m";
            showMenu(0);
            printGame();
            
            if(index1 == 63){
                showMenu(0);
                printGame();
                printf("\n\n\t\tgana: verde\n");
            }
        
            if(game[index1].action == "_│"){
               game[index1].player1 = "\e[1;42m  \e[0m";
               showMenu(0);
               printGame();
               turn=2;
            }
            else
                turn=1;
        }
        
        else if(turn=2){
            if(index2 > 63) index2 = 63 - (index2 - 63);
            movs2++;
            game[index2].player2 = "\e[1;34m─┐\e[0m";

            dice = 1 + (random() % 5);
            index2 = index2 + dice;
            game[index2].player2 = "\e[1;44m  \e[0m";
            showMenu(0);
            printGame();
            
            if(index2 == 63){
                showMenu(0);
                printGame();
                printf("\n\n\t\tgana: azul\n");
            }

            if(game[index2].action == "_│"){
               game[index2].player2 = "\e[1;44m  \e[0m";
               showMenu(0);
               printGame();
               turn=1;
            }
            else 
                turn=2;
        }
    nanosleep(&turnt, NULL);
    }
    
    printf("\n\t\tmovs1= %d & movs2= %d\n\n", movs1, movs2);
    
}

int runInteractive(){
    
    char option;
    
    initGame();
    showMenu(1);
    
    game[63].player1= "┌─";
    game[63].player2= "─┐";
    game[48].player2 = "─┐";
    game[1].player1 = "\e[1;42m  \e[0m";
    game[1].player2 = "\e[1;44m  \e[0m";
    
    while((game[63].player1 == "┌─") && (game[63].player2 == "─┐")){
    
        showMenu(0);
        printGame();
        printf("\n\n\n\t\t\tOpción: ");
        scanf("%c",&option);
        
        switch(option){
            
            case '1':
                
                initGame();
                showMenu(0);
                game[1].player1 = "\e[1;42m  \e[0m";
                game[1].player2 = "\e[1;44m  \e[0m";
                printGame();
                
                break;
                
            case '2':
                printf("option: 2");
                break;
                
            case '3':
                runDemo();
                break;
            
            case '4':
                printf("option: 4");
                break;
                
            case '5':
                printf("option: 5");
                break;
            
            case '0':
                printf("option: 0");
                return 0;
            
                
        }
    }
}

void runAuto(){
   
    int turn=1, index1=1, index2=1, movs=0, movs1=0, movs2=0, dice ;
    srandom (time (0));    
    initGame();
        
    while((game[63].player1 == "┌─") && (game[63].player2 == "─┐")){
        if(turn==1){
            if(index1 > 63) index1 = 63 - (index1 - 63);
            movs1++;
            game[index1].player1 = "\e[1;32m┌─\e[0m";
            
            dice = 1 + (random() % 5);
            index1 = index1 + dice;
            game[index1].player1 = "\e[1;42m  \e[0m";
                    
            if(game[index1].action == "_│"){
               game[index1].player1 = "\e[1;42m  \e[0m";
               turn=2;
            }
            else
                turn=1;
        }
        
        else if(turn=2){
            if(index2 > 63) index2 = 63 - (index2 - 63);
            movs2++;
            game[index2].player2 = "\e[1;34m─┐\e[0m";

            dice = 1 + (random() % 5);
            index2 = index2 + dice;
            game[index2].player2 = "\e[1;44m  \e[0m";
                        
            if(game[index2].action == "_│"){
               game[index2].player2 = "\e[1;44m  \e[0m";
               turn=1;
            }
            else 
                turn=2;
        }
   
    }
    
    //printf("\n\t\tmovs1= %d & movs2= %d\n\n", movs1, movs2);
    
    if(movs1 > movs2) movs = movs1;
    else movs = movs2;
    printf("%d\n",movs);
    
}