import random as rd 


## Q1
def etiquette_en_jeu(etiquette):
    a,b=etiquette.split('|')
    b=b.split(',')
    return a,[int(k) for k in b]

## Q2    
def jeu_en_etiquette(jeu):
    texte=jeu[0]+'|'
    for k in jeu[1]:
        texte+=str(k)+','
    return texte[:-1]

## Q3
def terminaux(etiquette):
    joueur,jeu=etiquette_en_jeu(etiquette)
    if jeu[0:6]==[0,0,0,0,0,0] or jeu[7:13]==[0,0,0,0,0,0]:
        return True
    else:
        return False




## fonction affichage
def affichage(etiquette):
    joueur,jeu=etiquette_en_jeu(etiquette)
    print('   ' + '|' + str(jeu[-2]) + '|' + str(jeu[-3]) + '|' + str(jeu[-4]) + '|' + str(jeu[-5]) + '|' + str(jeu[-6]) + '|' + str(jeu[-7]) + '|'+'   ')
    print(str(jeu[-1])+' '*(3-len(str(jeu[-1])))+'-'*13+' '*(3-len(str(jeu[6])))+str(jeu[6]))
    print('   ' + '|' + str(jeu[0]) + '|' + str(jeu[1]) + '|' + str(jeu[2]) + '|' + str(jeu[3]) + '|' + str(jeu[4]) + '|' + str(jeu[5]) + '|'+'   ')





## Q4 ITERATIVE
def graphemancala_ite(profondeur=7,etiquette='0|4,4,4,4,4,4,0,4,4,4,4,4,4,0',S=[],A=[],E=[]):
    S=[0]
    prof_list=[0]
    A=[]
    E=[etiquette]
    list_attente=[0]
    indice=0
    while indice<len(list_attente):
        indice_sommet=list_attente[indice]
        prof=prof_list[indice_sommet]
        etiquette=E[indice_sommet]
        joueur,jeu=etiquette_en_jeu(etiquette)
        if (not terminaux(etiquette)) and prof<profondeur:
            if joueur=="0":
                for s in range(6):
                    billes=jeu[s]
                    if billes!=0:
                        jeu_new=[k for k in jeu] 
                        jeu_new[s]=0
                        for l in range(1,billes+1):
                            jeu_new[(s+l)%14]+=1
                        if (s+billes)%14!=6:
                            joueur_new="1"
                        else:
                            joueur_new="0"
                        if jeu_new[(s+billes)%14]==1 and 0<=(s+billes)%14<=5:
                            billes_recup=jeu_new[12-((s-billes)%14)]
                            jeu_new[12-((s-billes)%14)]=0
                            jeu_new[6]+=billes_recup
                        etiquette_new=jeu_en_etiquette((joueur_new,jeu_new))
                        ind_new_sommet=len(S)
                        S.append(ind_new_sommet)
                        A.append([indice_sommet,ind_new_sommet])
                        E.append(etiquette_new)
                        prof_list.append(prof+1)
                        list_attente.append(ind_new_sommet)
            if joueur=="1":
                for s in range(7,13):
                    billes=jeu[s]
                    if billes!=0:
                        jeu_new=[k for k in jeu] 
                        jeu_new[s]=0
                        for l in range(1,billes+1):
                            jeu_new[(s+l)%14]+=1
                        if (s+billes)%14!=13:
                            joueur_new="0"
                        else:
                            joueur_new="1"
                        if jeu_new[(s+billes)%14]==1 and 7<=(s+billes)%14<=12 :
                            billes_recup=jeu_new[12-(s+billes)%14]
                            jeu_new[12-(s+billes)%14]=0
                            jeu_new[13]+=billes_recup
                        etiquette_new=jeu_en_etiquette((joueur_new,jeu_new))
                        ind_new_sommet=len(S)
                        S.append(ind_new_sommet)
                        A.append([indice_sommet,ind_new_sommet])
                        E.append(etiquette_new)
                        prof_list.append(prof+1)
                        list_attente.append(ind_new_sommet)

        indice=indice+1
    return S,A,E



## Q4 RECURSIVE
def ajout_sous_arbre(T,t,f):
    ''' 
    A REMPLIR
    '''
    S,A,E=T
    s,a,e=t
    l=len(S)
    for k in s:
        S.append(k+l)
    for (s1,s2) in a:
        A.append([s1+l,s2+l])
    E=E+e
    A.append([f,l])
    return S,A,E
    
    
def graphemancala_rec(n,etiquette='0|4,4,4,4,4,4,0,4,4,4,4,4,4,0',S=[],A=[],E=[],i=0):
    if i==0:
        S=[0]
        A=[]
        E=[etiquette]
    if n==i:
        return S,A,E
    joueur,jeu=etiquette_en_jeu(etiquette)
    p=len(S)-1
    if not terminaux(etiquette):
        if joueur=="0":
            for s in range(6):
                billes=jeu[s]
                if billes!=0:
                    jeu_new=[k for k in jeu] 
                    jeu_new[s]=0
                    for l in range(1,billes+1):
                        jeu_new[(s+l)%14]+=1
                    if (s+billes)%14!=6:
                        joueur_new="1"
                    else:
                        joueur_new="0"
                    if jeu_new[(s+billes)%14]==1 and 0<=(s+billes)%14<=5:
                        billes_recup=jeu_new[12-((s-billes)%14)]
                        jeu_new[12-((s-billes)%14)]=0
                        jeu_new[6]+=billes_recup
                    etiquette_new=jeu_en_etiquette((joueur_new,jeu_new))
                    T=S,A,E
                    t=graphemancala_rec(n,etiquette_new,[0],[],[etiquette_new],i+1)
                    S,A,E=ajout_sous_arbre(T,t,p)
        if joueur=="1":
            for s in range(7,13):
                billes=jeu[s]
                if billes!=0:
                    jeu_new=[k for k in jeu] 
                    jeu_new[s]=0
                    for l in range(1,billes+1):
                        jeu_new[(s+l)%14]+=1
                    if (s+billes)%14!=13:
                        joueur_new="0"
                    else:
                        joueur_new="1"
                    if jeu_new[(s+billes)%14]==1 and 7<=(s+billes)%14<=12 :
                        billes_recup=jeu_new[12-(s+billes)%14]
                        jeu_new[12-(s+billes)%14]=0
                        jeu_new[13]+=billes_recup
                    etiquette_new=jeu_en_etiquette((joueur_new,jeu_new))
                    T=S,A,E
                    t=graphemancala_rec(n,etiquette_new,[0],[],[etiquette_new],i+1)
                    S,A,E=ajout_sous_arbre(T,t,p)
    return S,A,E
    
    

graphemancala=graphemancala_ite #je choisis quelle fonction j'utilise pour la suite



## Q5
    
def sommets_controlés(S,A,E):
    cont=[]
    for k in range(len(E)):
        if E[k][0]=="0":
            cont.append(k)
    return cont
                
    

## Q6        
def valeur(etiquette):
    joueur,jeu=etiquette_en_jeu(etiquette)
    if jeu[0:6]==[0,0,0,0,0,0] or jeu[7:13]==[0,0,0,0,0,0]:
        return jeu[6]+sum(jeu[0:6])-jeu[13]-sum(jeu[7:13])
    else:
        return jeu[6]-jeu[13]
        
        


## Q7

def marq_et_prop(x,value,compt,suc,pred,S0,F):
    """
    A REMPLIR
    """
    if x in S0 and x not in F:
        value[x]=max([value[s] for s in suc[x]])
    elif x not in S0 and x not in F : 
        value[x]=min([value[s] for s in suc[x]]) 
    for u in pred[x]:
        compt[u]=compt[u]-1
        if compt[u]==0:
            value,compt=marq_et_prop(u,value,compt,suc,pred,S0,F)
    return value,compt
    
    
    

def predsuccesseur(S,A):
    """
    La fonction prend en paramètres :
    S: une liste d'entiers, qui correspond aux sommets d'un graphe
    A: une liste de tuples d'entiers (i,j), qui correspondent aux arêtes d'un graphe
    
    La fonction renvoie un tuple contenant 4 listes:
    suc: une liste de listes, où chaque sous-liste contient les successeurs d'un sommet de S
    nbsuc: une liste contenant le nombre de successeurs pour chaque sommet de S
    pred: une liste de listes, où chaque sous-liste contient les prédécesseurs d'un sommet de S
    nbpred: une liste contenant le nombre de prédécesseurs pour chaque sommet de S.
    En utilisant les informations fournies par S et A, cette fonction permet de construire les listes des successeurs et prédécesseurs pour chaque sommet du graphe, ainsi que le nombre de successeurs et prédécesseurs pour chaque            sommet.
    """
    suc=[[] for i in S]
    nbsuc=[0 for i in S]
    pred=[[] for i in S]
    nbpred=[0 for i in S]
    for (i,j) in A:
        suc[i].append(j)
        pred[j].append(i)
        nbpred[j]+=1
        nbsuc[i]+=1
    return suc,nbsuc,pred,nbpred
    
    
    
    
def minimax(S:list,A:list,E:list,S0:list,valeur)->list:
    '''
    A REMPLIR
    '''
    value=["" for i in S]
    suc,nbsuc,pred,nbpred=predsuccesseur(S,A)
    F=[]
    for k in range(len(nbsuc)):
        if nbsuc[k]==0:
            F.append(k)
    for i in range(len(F)):
        value[F[i]]=valeur(E[F[i]])
    compt=nbsuc
    for x in F:
        value,compt=marq_et_prop(x,value,compt,suc,pred,S0,F)
    L=[]
    for k in suc[0]:
        if value[k]==value[0]:
            L.append(k)
    return value, E[rd.choice(L)]
            

    

    
    
    
  

## Q8
    
def jouer(etiquette):
    billes=-1
    while billes<=0:
        if billes==0:
            print("mauvaise case, il n'y a plus de bille dans celle-ci ou c'est une case non valide")
        s=input("quelle case jouée : ")
        s=int(s)
        if s>5:
            billes=0
        else:
            joueur,jeu=etiquette_en_jeu(etiquette)
            billes=jeu[s]
    jeu_new=[k for k in jeu] 
    jeu_new[s]=0
    for l in range(1,billes+1):
        jeu_new[(s+l)%14]+=1
    if (s+billes)%14!=6:
        joueur_new="1"
    else:
        joueur_new="0"
    if jeu_new[(s+billes)%14]==1 and 0<=(s+billes)%14<=5:
        billes_recup=jeu_new[12-(s+billes)%14]
        jeu_new[12-(s+billes)%14]=0
        jeu_new[6]+=billes_recup
    etiquette_new=jeu_en_etiquette((joueur_new,jeu_new))
    return etiquette_new   
    
    
## Q9
  
def game(etiquette='0|4,4,4,4,4,4,0,4,4,4,4,4,4,0'):
    affichage(etiquette)
    while not terminaux(etiquette):
        if etiquette[0]=='0':
            etiquette=jouer(etiquette)
            affichage(etiquette)
        else:
            print("Vador réfléchit")
            S,A,E=graphemancala(6,etiquette)
            v,etiquette=minimax(S,A,E,sommets_controlés(S,A,E),valeur)
            print("Vador joue:")
            affichage(etiquette)
            print("évaluation de l'état de la partie par le seigneur du mal : ",v[0])
    note=valeur(etiquette)
    if note >0:
        print("vous avez gagné!")
    elif note==0:
        print("match nul")
    else:
        print("vous avez perdu!")



    