from random import randint

choices = ["p","f","c","q"]
names = {"p": "Pierre", "f": "Feuille", "c": "Ciseaux"}
bat = {"p" : "f", "c" : "p", "f" : "c"}

class Player:
    def __init__(self):
        pass
    def move(self):
        pass
    def update_strategy(self, cplayer):
        pass

class HumanPlayer(Player):
    def move(self):
        c=""
        while(c not in choices):
            c=input("Pierre (p) Feuille (f) Ciseau (c) ? (q pour quitter)")
        return c

class RandomPlayer(Player):
    def move(self):
        return choices[randint(0,2)]

    
class StocPlayer(Player):
    def __init__(self):
        self.stat = {f"{c1}{c2}{c3}" : 0 for c1 in names for c2 in names for c3 in names}
        self.last = ""
        
    def move(self):
        if len(self.last)<2:
            return choices[randint(0,2)]
        else:
            return bat[max("pfc", key=lambda x: self.stat[self.last+x])]
        
    def update_strategy(self, c):
        if len(self.last) < 2:
            self.last+=c
        else:
            self.stat[self.last+c] += 1
            self.last = self.last[-1]+c

# Pour battre le joueur stochastique, on simule sa stratégie, ce qui
# permet de deviner le coup qu'il va jouer. On joue alors le coup
# inverse ! Cela marche car la stratégie du joueur stochastique est
# déterministe...

class BeatStocPlayer(Player):
    def __init__(self):
        self.stat = {f"{c1}{c2}{c3}" : 0 for c1 in names for c2 in names for c3 in names}
        self.last = ""

    def move(self):
        # on simule la stratégie de l'IA stochastique
        if len(self.last)<2:
            r = choices[randint(0,2)]
        else:
            r = bat[max("pfc", key=lambda x: self.stat[self.last+x])]
            
        # On choisit le coup contraire
        c = bat[r]
        
        # On met à jour la structure interne
        if len(self.last) < 2:
            self.last+=c
        else:
            self.stat[self.last+c] += 1
            self.last = self.last[-1]+c
        
        return c
        
class Pfc:
    def __init__(self,p1: Player, p2: Player):
        self.score=[0]*2
        self.Player1 = p1
        self.Player2 = p2
        
    def play(self):
        while (self.score[0] < 50 and self.score[1] < 50):
            c1 = self.Player1.move()
            c2 = self.Player2.move()

            if c1 == "q" or c2 == "q":
                break

            if c1 not in choices or c2 not in choices:
                continue
        
            print(f"Player1 played {names[c1]} \t Player2 played {names[c2]}")
        
            if c1 == c2:
                print("Draw!")
            else:
                if (c1=="p" and c2=="f") or (c1=="f" and c2=="c") or (c1=="c" and c2=="p"):
                    self.score[1] += 1
                    print("Player2 wins!")
                else:
                    self.score[0] += 1
                    print("Player1 wins!")
                
            print(f"Scores: \t Player 1: {self.score[0]} \t Player 2: {self.score[1]}")

            # mise à jour des stats
            self.Player1.update_strategy(c2)
            self.Player2.update_strategy(c1)
        
def main():
    game = Pfc(StocPlayer(), RandomPlayer())
    game.play()
    
if __name__ == "__main__":
    main()
