#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

struct jeu {
    int scorej1;
    int scorej2;
    int* plateauj1;
    int* plateauj2;
    int tour;
};

typedef struct jeu jeu;

jeu* initialisation(void){
    jeu* res=malloc(sizeof(jeu));
    res->scorej1=0;
    res->scorej2=0;
    res->plateauj1 = malloc(6*sizeof(int));
    res->plateauj2 = malloc(6*sizeof(int));
    for (int i=0;i<6;i++){
        res->plateauj1[i]=4;
        res->plateauj2[i]=4;
    }
    res->tour=0;
    return res;
}
bool tour_joueur1(jeu* j){
    return ((j->tour)%2==0);
}

jeu* copie(jeu* j){
    jeu* new_jeu = initialisation();
    new_jeu->scorej1=j->scorej1;
    new_jeu->scorej2=j->scorej2;
    new_jeu->tour=j->tour;
    for (int i=0;i<6;i++){
        new_jeu->plateauj1[i]=j->plateauj1[i];
        new_jeu->plateauj2[i]=j->plateauj2[i];
    }
    return new_jeu;

}

int deplacer_graines(jeu* j, int casenb){

    if (tour_joueur1(j)){
       // printf("depose par J1\n");
        int nb_graines=j->plateauj1[casenb];
        int indice = (casenb + 1);
        int indice_save = indice;
        j->plateauj1[casenb]=0;
        while(nb_graines > 0){
            if (indice <6){
                if (indice != casenb){
                j->plateauj1[indice]++;
                nb_graines--;
                }
                indice_save=indice;
                indice++;
                
            }
            else {
                j->plateauj2[indice-6]++;
                indice_save=indice;
                indice=(indice+1)%12;
                nb_graines--;

            }
        }
        return indice_save;



    }
    else {
       // printf("depose par J2\n");
        int nb_graines=j->plateauj2[casenb];
        int indice = (casenb + 1)%12;
        int indice_save=indice;
        
        j->plateauj2[casenb]=0;
        while(nb_graines > 0){
            if (indice <6){
                if (indice!=casenb){
                j->plateauj2[indice]++;
                indice_save=indice;
                indice++;
                nb_graines--;
                }
                
            }
            else{
                j->plateauj1[indice-6]++;
                indice_save=indice;
                indice=(indice+1)%12;
                nb_graines--;

            }
        }


    return indice_save;
    }
    
}

bool case_ramassable(jeu* j, int casenb){
    //printf("Tour %d\n",j->tour);
    if (tour_joueur1(j)){
        //printf("ramasser J1\n");
        return (casenb >= 6 && (j->plateauj2[casenb-6]==2 || j->plateauj2[casenb-6]==3));
    }
    else {//printf("ramasser J2\n");
        return (casenb >= 6 && (j->plateauj1[casenb-6]==2 || j->plateauj1[casenb-6]==3));
    }

    
}

int ramasser_graines(jeu* j, int casenb){
    if (tour_joueur1(j)){
            if (case_ramassable(j,casenb)){
                int save = j->plateauj2[casenb-6];
                j->plateauj2[casenb-6]=0;
                return(save+ramasser_graines(j,(casenb-1)));
            }
            else return 0;
        
    }
    else {
            if (case_ramassable(j,casenb)){
                int save = j->plateauj1[casenb-6];
                j->plateauj1[casenb-6]=0;
                return(save+ramasser_graines(j,(casenb-1)));
            } else return 0;
        
    }
    

}
void libere(jeu* j){
    free(j->plateauj1);
    free(j->plateauj2);
    free(j);
}

void affiche (jeu* j){
    printf("Tour num : %d\n.", j->tour);
    printf("Score J1 : %d\n.", j->scorej1);
    printf("Score J2 : %d\n.", j->scorej2);
    if (tour_joueur1(j)){
        printf("plateau J2 :");
        for (int i=5;i>=0;i--){
            printf("  %d  ", j->plateauj2[i]);

        }
        printf("\n");
        printf("plateau J1 :");
        for (int i=0;i<6;i++){
            printf("  %d  ", j->plateauj1[i]);

        }
    
    }
    else {
        printf("plateau J1 :");
        for (int i=5;i>=0;i--){
            printf("  %d  ", j->plateauj1[i]);

        }
        printf("\n");
        printf("plateau J2 :");
        for (int i=0;i<6;i++){
            printf("  %d  ", j->plateauj2[i]);

        }
    
    }
}

bool test_famine(jeu* j, int casenb){
    //printf("debut test case %d\n", casenb);
    jeu* save = copie(j);
    //affiche(save);
    int case_fin = deplacer_graines(save,casenb);
    //affiche(save);
    ramasser_graines(save,case_fin);
    if (tour_joueur1(j)){
        for (int i=0;i<6;i++){
            if (save->plateauj2[i]!=0){
                libere(save);
               // printf("fin test\n");
                return true;
            }
        }
    }
    else{
           for (int i=0;i<6;i++){
            if (save->plateauj1[i]!=0){
                libere(save);
                //printf("fin test\n");
                return true;
            }
        }
    }
     libere(save);
        //printf("fin test\n");
        return false;


}



bool test_case (jeu* j, int casenb){
    if (tour_joueur1(j))
        return(casenb >=0 && casenb<6 && j->plateauj1[casenb]!=0 && test_famine(j,casenb));
    else 
        return(casenb >=0 && casenb<6 && j->plateauj2[casenb]!=0 && test_famine(j,casenb));
}

bool cases_possibles(jeu* j,bool* tab){
    for (int i=0;i<6;i++){
        tab[i]=test_case(j,i);
    }
    for (int i=0;i<6;i++){
        if (tab[i]) return true;
    }
    return false;
}


bool tour_suivant(jeu* j,int* tab){
    return !(j->scorej1>=25 || j->scorej2>=25 || j->tour>=100 || j->scorej1+j->scorej2>=45 || !(cases_possibles(j,tab)));
}

bool tour_jeu(jeu* j, int casenb, int* tab){
    if (test_case(j,casenb)){
        //printf("case choisie %d\n", casenb);
        int indice_fin = deplacer_graines(j,casenb);
        //printf("indice fin : %d\n", indice_fin);
        int ajout_score = ramasser_graines(j,indice_fin);
        //printf("gain : %d\n", ajout_score);
        if (tour_joueur1(j)){
            j->scorej1+=ajout_score;
        }
        else{
            j->scorej2+=ajout_score;
        }
        j->tour++;
        return (tour_suivant(j,tab));
    }
    else{
        printf("La case choisie n'est pas valable\n");
        return true;
    }
}


int gagnant (jeu* j){
    for (int i=0;i<6;i++){
        j->scorej1+=j->plateauj1[i];
        j->scorej2+=j->plateauj2[i];

    }
    if (j->scorej1>j->scorej2){
        return 1;
    }
    else if (j->scorej1>j->scorej1){
        return 2;
    }
    else return 0;
    
}

int awale_jcj(void){
    jeu* j = initialisation();
    bool jeu_continue = true;
    int* tab = malloc(6*sizeof(int)); 
    while(jeu_continue){
        if (tour_joueur1(j)) printf("\nc'est au J1\n");
        else printf("\nc'est au J2\n");
        affiche(j);
        printf("\n");
        int case_choisie;
        printf("Choisir une case : \n");
        scanf("%d", &case_choisie);
        printf("vous avez choisi la case %d\n", case_choisie);
        jeu_continue = tour_jeu(j,case_choisie,tab);

    }
    free(tab);
    return (gagnant(j));
}

int main(){
    awale_jcj();


}
