# dilemme du prisonnier itéré
# version tournoi

from random import *

choix = ['T','C']  # T : trahit, C : coopère

def gain(lui,moi):
    if lui=='C' and moi=='C':
        return 3
    elif lui=='C' and moi=='T':
        return 5
    elif lui=='T' and moi=='C':
        return 0
    elif lui=='T' and moi=='T':
        return 1


# Toujours seul
# ne coopère jamais

def toujours_seul(liste_lui,liste_moi):
    return 'T'


# Bonne poire
# coopère toujours

def bonne_poire(liste_lui,liste_moi):
    return 'C'


# Aléatoire
# joue avec une probabilité égale 'T' ou 'C'

def aleatoire(liste_lui,liste_moi):
    global choix
    return choice(choix)


# Donnant donnant
# coopère seulement si l'autre joueur a coopéré au coup précédent.

def donnant_donnant(liste_lui,liste_moi):
    if len(liste_lui)>0:
        return liste_lui[-1]
    else:  # premier coup
        return 'C'


# Majorité
# coopère seulement si l'autre joueur a coopéré en majorité.

def majorite(liste_lui,liste_moi):
    if len(liste_lui)>0:
        if liste_lui.count('C') > len(liste_lui)//2:
            return 'C'
        else:
            return 'T'
    else:  # premier coup
        return 'C'


# Ajouter les stratégies des joueurs ici

# Coyote
# Coopère toujours les deux premiers coups
# Trahit au hasard dans 45 % des cas
# S'il ne trahit pas d'abord, coopère seulement si l'autre joueur a coopéré les deux derniers coups


def coyote(liste_lui,liste_moi):
    if len(liste_lui)>1:
        if random() > 0.55:
            return 'T'
        else:
            if liste_lui[-1]=='C' and liste_lui[-2]=='C' :
                return 'C'
            else:
                return 'T'
    else:  # premiers coups
        return 'C'


# Lola
# Coopère au premier coup
# Joue ce que l'autre a joué au coup précédent
# Dès que l'autre a trahi 3 fois, trahit tout le temps

def lola(liste_lui, liste_moi):
    if len(liste_lui)>0:
        if liste_lui.count('T')>=3:
            return 'T'
        else:
            return liste_lui[-1]
    else:
        return 'C'


# Doreen
# Si l'adversaire a coopéré au tour précédent, on trahit ; s'il a trahi, on coopère.
def doreen(liste_lui,liste_moi):
    if len(liste_lui)>0:
        if liste_lui[-1] == 'C':
            return 'T'
        elif liste_lui[-1] == 'T':
            return 'C'
    else:  # premier coup
        return 'C'


# Alyssa
# joue le même coup s'il est joué deux fois de suite sinon joue l'avant dernier coup
def alyssa(liste_lui,liste_moi):
    if len(liste_lui)>2:
        if liste_lui[-1]=='C' and liste_lui[-2]=='C':
            return 'C'
        elif liste_lui[-1]=='T' and liste_lui[-2]=='T':
            return 'T'
        elif liste_lui[-1]=='T' and liste_lui[-2]=='C':
            return 'T'
        elif liste_lui[-1]=='C' and liste_lui[-2]=='T':
            return 'C'
    else:
        return 'T'

# Amélie
# donnant-donnant sauf si l'autre trahit en majorité, dans ce cas-là on trahit tout le temps

def amelie(liste_lui,liste_moi):
    if len(liste_lui)>0:
        if liste_lui.count('C') > len(liste_lui)//2:
            return liste_lui[-1]
        else:
            return 'T'
    else:  # premier coup
        return 'C'


#Florian
#alors ben en gros ben ça regarde si la liste à déjà un élément sinon ça joue C.
#après ben ça regarde si il joue contre lui même et faire v'la les points en mettant toujours C
#puis il regarde si il joue contre un bot pas très futé qui joue toujours la même chose et le défonce en mettant toujours T
#et pis ben sinon ben euhh il joue T deux fois sur trois quoi euhh ben voilà
#bonne journée

n=0
def florian(liste_lui, liste_moi):
    global n

    n+=1
    if len(liste_lui)<1:
        return "C"

    if liste_lui == liste_moi:
        return "C"

    x=0
    meme=0
    pasmeme=0
    while x+1<len(liste_lui):
        if liste_lui[x] == liste_lui[x+1]:
            meme+=1
        else:
            pasmeme+=1
        x+=1

    if pasmeme == 0 and meme<1:
        return "T"

    else:
        if n%3==0 or n%3==1:
            return "T"
        else:
            return "C"


#Cristobal
#Coopère les 2 premiers coups, puis coopère jusqu'à ce que l'adversaire trahisse.

def cristobal(liste_lui,liste_moi):
    if len(liste_lui)>2:
         if liste_lui[-1]== 'T' or liste_moi[-1]== 'T':
             return 'T'
         else:
             return 'C'
    else:
        return 'C'


#Lowell
# donnant_donnant (l): donant_donant mais les deux premiers coup tire soit T ou C

def lowell(liste_lui,liste_moi):
    global choix
    if len(liste_lui)>2:
        return liste_lui[-1]
    else: # premiers coups
        return choice(choix)


# Augustin
# c'est une stratégie qui essai de détecter si son adversaire s'adapte à elle
# si l'adversaire s'adapte alors elle joue C et sinon elle joue T
# oui c'est un peut long désolé 😄

def augustin(liste_lui, liste_moi):
    global finded
    global strat

    if len(liste_lui)<=0:
        finded = False
        strat = 0
        return 'C'
    elif len(liste_lui) == 1 and finded == False:
        if liste_lui[0] != 'C':
            finded = True
            strat = 1
        return 'T'
    elif len(liste_lui) == 2 and finded == False:
        return 'C'
    elif len(liste_lui) == 3 and finded == False:
        if liste_lui[1] == 'T' and liste_lui[2] == 'C':
            finded = True
            strat = 2
        return 'C'

        return 'C'
    elif len(liste_lui) == 4 and finded == False:
        if liste_lui[2] == 'T' and liste_lui[3] == 'C':
            finded = True
            strat = 2
            return 'C'
        else:
            finded = True
            strat = 1
            return 'T'

    else:
        if strat == 1:
            return 'T'

        else:
            return 'C'



# Le tournoi

liste = {}
strategie = {}
score = {}
duel = {}

# ajouter des joueurs ci-dessous, selon les modèles des joueurs existants
# commencer ici
liste['Toujours seul'] = []
liste['Bonne poire'] = []
liste['Majorité'] = []
liste['Aléatoire'] = []
liste['Donnant donnant'] = []
liste['Coyote'] = []
liste['Lola'] = []
liste['Doreen'] = []
liste['Alyssa'] = []
liste['Amélie'] = []
liste['Florian'] = []
liste['Cristobal'] = []
liste['Augustin'] = []
liste['Lowell'] = []

# ...

strategie['Toujours seul'] = lambda lui, moi : toujours_seul(lui,moi)
strategie['Bonne poire'] = lambda lui, moi : bonne_poire(lui,moi)
strategie['Majorité'] = lambda lui, moi : majorite(lui,moi)
strategie['Aléatoire'] = lambda lui, moi : aleatoire(lui,moi)
strategie['Donnant donnant'] = lambda lui, moi : donnant_donnant(lui,moi)
strategie['Coyote'] = lambda lui, moi : coyote(lui,moi)
strategie['Lola'] = lambda lui, moi : lola(lui,moi)
strategie['Doreen'] = lambda lui, moi : doreen(lui,moi)
strategie['Alyssa'] = lambda lui, moi : alyssa(lui,moi)
strategie['Amélie'] = lambda lui, moi : amelie(lui,moi)
strategie['Florian'] = lambda lui, moi : florian(lui,moi)
strategie['Cristobal'] = lambda lui, moi : cristobal(lui,moi)
strategie['Augustin'] = lambda lui, moi : augustin(lui,moi)
strategie['Lowell'] = lambda lui, moi : lowell(lui,moi)

# terminer là

nb_total_coups = 6734  # à modifier

for joueur in liste.keys():
    score[joueur] = 0

for i in liste.keys():  # i et j sont les joueurs
    for j in liste.keys() :
        liste[i] = []   # on recommence une partie
        liste[j] = []
        if i>=j:
            nb_coups = 0
            score_joueur1 = 0
            score_joueur2 = 0
            seed(97989) # germe du générateur aléatoire
            while nb_coups < nb_total_coups :
                coup_joueur1 = strategie[i](liste[j],liste[i])
                coup_joueur2 = strategie[j](liste[i],liste[j])
                liste[i].append(coup_joueur1)
                if i!=j:
                    liste[j].append(coup_joueur2)
                score_joueur1 += gain(coup_joueur2,coup_joueur1)
                score_joueur2 += gain(coup_joueur1,coup_joueur2)
                nb_coups += 1
            duel[(i,j)] = score_joueur1
            if i!=j:
                duel[(j,i)] = score_joueur2
            score[i] += score_joueur1
            if i!=j:
                score[j] += score_joueur2

# affichage des résultats

def trie_par_valeur(d):
    #retourne une liste de tuples triée selon les valeurs
    return sorted(d.items(), key=lambda x: x[1])

def trie_par_cle(d):
    #retourne une liste de tuples triée selon les clés
    return sorted(d.items(), key=lambda x: x[0])

score_trie = trie_par_valeur(score)
score_trie.reverse()
for i in range(0,len(score_trie)):
    print(score_trie[i][0],":",score_trie[i][1])
print()
duel_trie = trie_par_cle(duel)
for i in range(0,len(duel_trie)):
    print(duel_trie[i][0][0],"contre",duel_trie[i][0][1],"gagne",duel_trie[i][1],"pts")

