From 9ca3dca68bc717d33f9e1abcf07813dd3b63450c Mon Sep 17 00:00:00 2001
From: unknown <22013326@etu.unicaen.fr>
Date: Mon, 10 Mar 2025 20:17:06 +0100
Subject: [PATCH] Tournoi OK

---
 TP1/Tournoi.py | 249 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 249 insertions(+)
 create mode 100644 TP1/Tournoi.py

diff --git a/TP1/Tournoi.py b/TP1/Tournoi.py
new file mode 100644
index 0000000..551b336
--- /dev/null
+++ b/TP1/Tournoi.py
@@ -0,0 +1,249 @@
+import random
+
+class Prisonnier:
+    """
+    Classe représentant un prisonnier avec une stratégie basée sur une probabilité d'avouer.
+    """
+    def __init__(self, proba_avouer=0.5, nom="Prisonnier Aléatoire"):
+        """
+        Constructeur de la classe Prisonnier.
+        
+        Args:
+            proba_avouer: probabilité d'avouer (par défaut 0.5 pour un joueur aléatoire uniforme)
+            nom: nom de la stratégie pour l'affichage
+        """
+        self.proba_avouer = proba_avouer
+        self.historique_adversaire = []
+        self.nom = nom
+    
+    def jouer(self):
+        """
+        Méthode qui détermine l'action du joueur en fonction de sa probabilité d'avouer.
+        
+        Returns:
+            'avoue' ou 'nie' selon la probabilité
+        """
+        if random.random() < self.proba_avouer:
+            return "avoue"
+        else:
+            return "nie"
+    
+    def maj(self, coup):
+        """
+        Méthode qui met à jour l'historique des coups joués par l'adversaire.
+        
+        Args:
+            coup: le coup joué par l'adversaire ('avoue' ou 'nie')
+        """
+        self.historique_adversaire.append(coup)
+    
+    def reinitialiser(self):
+        """
+        Méthode qui réinitialise l'historique des coups de l'adversaire.
+        """
+        self.historique_adversaire = []
+
+
+class TitForTat(Prisonnier):
+    """
+    Stratégie Tit for Tat (oeil pour oeil) : commence par coopérer (nier),
+    puis imite le dernier coup de l'adversaire.
+    """
+    def __init__(self):
+        """
+        Constructeur de la classe TitForTat.
+        """
+        super().__init__(nom="TitForTat")  # Appel du constructeur de la classe parente
+    
+    def jouer(self):
+        """
+        Méthode qui détermine l'action du joueur selon la stratégie Tit for Tat.
+        
+        Returns:
+            'avoue' ou 'nie' selon la stratégie
+        """
+        # Si c'est le premier coup, on coopère (nie)
+        if not self.historique_adversaire:
+            return "nie"
+        # Sinon, on imite le dernier coup de l'adversaire
+        else:
+            return self.historique_adversaire[-1]
+
+
+class Dummy(Prisonnier):
+    """
+    Stratégie Dummy : toujours coopérer ou toujours trahir selon un paramètre.
+    """
+    def __init__(self, coopere=True):
+        """
+        Constructeur de la classe Dummy.
+        
+        Args:
+            coopere: si True, toujours coopérer (nier), sinon toujours trahir (avouer)
+        """
+        nom = "Dummy (coopère)" if coopere else "Dummy (trahit)"
+        super().__init__(nom=nom)  # Appel du constructeur de la classe parente
+        self.coopere = coopere
+    
+    def jouer(self):
+        """
+        Méthode qui détermine l'action du joueur selon la stratégie Dummy.
+        
+        Returns:
+            'avoue' ou 'nie' selon la stratégie
+        """
+        if self.coopere:
+            return "nie"  # Coopérer = nier
+        else:
+            return "avoue"  # Trahir = avouer
+
+
+def dilemme_prisonnier_itere(matrice_pertes, joueur1, joueur2, nb_tours=10, afficher_details=False):
+    """
+    Fonction qui simule un dilemme du prisonnier itéré entre deux joueurs.
+    
+    Args:
+        matrice_pertes: dictionnaire des pertes
+        joueur1: premier joueur
+        joueur2: deuxième joueur
+        nb_tours: nombre de tours à jouer
+        afficher_details: si True, affiche les détails de chaque tour
+        
+    Returns:
+        tuple des scores totaux (score_joueur1, score_joueur2)
+    """
+    # Réinitialisation des historiques
+    joueur1.reinitialiser()
+    joueur2.reinitialiser()
+    
+    score_joueur1 = 0
+    score_joueur2 = 0
+    
+    if afficher_details:
+        print(f"Dilemme du prisonnier itéré: {joueur1.nom} vs {joueur2.nom}")
+        print(f"Nombre de tours: {nb_tours}")
+        print("-" * 50)
+    
+    for tour in range(nb_tours):
+        # Les joueurs choisissent leur action
+        action_joueur1 = joueur1.jouer()
+        action_joueur2 = joueur2.jouer()
+        
+        # On calcule les pertes pour ce tour
+        perte_joueur1, perte_joueur2 = matrice_pertes[(action_joueur1, action_joueur2)]
+        
+        # On met à jour les scores (négatif des pertes)
+        score_joueur1 -= perte_joueur1
+        score_joueur2 -= perte_joueur2
+        
+        # On met à jour l'historique des joueurs
+        joueur1.maj(action_joueur2)
+        joueur2.maj(action_joueur1)
+        
+        # Affichage du tour si demandé
+        if afficher_details:
+            print(f"Tour {tour+1}: {joueur1.nom} joue {action_joueur1}, {joueur2.nom} joue {action_joueur2}")
+            print(f"Pertes: {joueur1.nom} = {perte_joueur1}, {joueur2.nom} = {perte_joueur2}")
+            print(f"Scores cumulés: {joueur1.nom} = {score_joueur1}, {joueur2.nom} = {score_joueur2}\n")
+    
+    if afficher_details:
+        print("Résultat final:")
+        print(f"Score {joueur1.nom}: {score_joueur1}")
+        print(f"Score {joueur2.nom}: {score_joueur2}")
+        
+        if score_joueur1 > score_joueur2:
+            print(f"{joueur1.nom} gagne!")
+        elif score_joueur2 > score_joueur1:
+            print(f"{joueur2.nom} gagne!")
+        else:
+            print("Match nul!")
+        print("-" * 50)
+    
+    return score_joueur1, score_joueur2
+
+
+def organiser_tournoi_simple(matrice_pertes, joueurs, nb_tours=50):
+    """
+    Fonction qui organise un tournoi simple entre différentes stratégies.
+    
+    Args:
+        matrice_pertes: dictionnaire des pertes
+        joueurs: liste des joueurs
+        nb_tours: nombre de tours par partie
+        
+    Returns:
+        dictionnaire des scores totaux par joueur
+    """
+    scores = {joueur.nom: 0 for joueur in joueurs}
+    nb_matchs = {joueur.nom: 0 for joueur in joueurs}
+    
+    print("\nTournoi sur la matrice de pertes")
+    print("=" * 40)
+    
+    # Chaque joueur affronte tous les autres joueurs
+    for i, joueur1 in enumerate(joueurs):
+        for j, joueur2 in enumerate(joueurs):
+            if i != j:  # Un joueur ne s'affronte pas lui-même
+                score1, score2 = dilemme_prisonnier_itere(matrice_pertes, joueur1, joueur2, nb_tours=nb_tours)
+                
+                # On met à jour les scores totaux
+                scores[joueur1.nom] += score1
+                scores[joueur2.nom] += score2
+                
+                # On met à jour le nombre de matchs
+                nb_matchs[joueur1.nom] += 1
+                nb_matchs[joueur2.nom] += 1
+                
+                # On affiche les résultats de cette confrontation
+                print(f"{joueur1.nom} vs {joueur2.nom}: {score1} - {score2}")
+    
+    # On calcule les scores moyens
+    scores_moyens = {nom: scores[nom] / nb_matchs[nom] for nom in scores}
+    
+    # On trie les joueurs par score moyen décroissant
+    classement = sorted(scores_moyens.items(), key=lambda x: x[1], reverse=True)
+    
+    print("\nClassement final:")
+    for rang, (nom, score) in enumerate(classement, 1):
+        print(f"{rang}. {nom}: {score:.1f}")
+    
+    return scores_moyens
+
+
+# Main pour tester le code
+if __name__ == "__main__":
+    # Définition des actions possibles
+    actions = ["avoue", "nie"]
+    
+    # Représentation des pertes (peines) par un dictionnaire
+    pertes = {
+        ("avoue", "avoue"): (3, 3),
+        ("avoue", "nie"): (0, 10),
+        ("nie", "avoue"): (10, 0),
+        ("nie", "nie"): (1, 1)
+    }
+    
+    print("Dilemme du Prisonnier Itéré")
+    print("===========================")
+    
+    # Création des joueurs avec différentes stratégies
+    joueurs = [
+        TitForTat(),
+        Dummy(coopere=True),
+        Dummy(coopere=False),
+        Prisonnier(proba_avouer=0.5),
+        Prisonnier(proba_avouer=0.3, nom="Prisonnier (p=0.3)")
+    ]
+    
+    # Test de différentes combinaisons de stratégies
+    print("\nTest de différentes combinaisons de stratégies")
+    print("-------------------------------------------")
+    
+    # TitForTat vs Dummy (trahit)
+    dilemme_prisonnier_itere(pertes, joueurs[0], joueurs[2], nb_tours=10, afficher_details=True)
+    
+    # TitForTat vs Dummy (coopère)
+    dilemme_prisonnier_itere(pertes, joueurs[0], joueurs[1], nb_tours=10, afficher_details=True)
+    
+    # Organisation d'un tournoi simple
+    organiser_tournoi_simple(pertes, joueurs, nb_tours=50)
\ No newline at end of file
-- 
GitLab