class Game(int): def __init__(self, start): #Game variables self.matches = start # number of matches self.state = 0 #-1 = lost, 0 = draw, +1 = won self.playerTurn = 1 # 1 = player 1 is playing, 2 = player 2 is playing #Algorithm variables self.exploreMaxCalls = 0 # Call counter of exploreMax self.exploreMinCalls = 0 # Call counter of exploreMax self.firstPlayerWinning = False # Result of MinMax self.algorithmResFound = False # True if MiniMax algorithm found a result def miniMax(self): ''' `miniMax` function starts the MiniMax algorithm Params : self -- the current instance of the game Return : -1 = lost or 0 = draw or +1 = won -- depends on the possibility to win of the player ''' self.algorithmResFound = False if(self.playerTurn == 1): res = self.exploreMax(self.matches) if(self.playerTurn == 2): res = self.exploreMin(self.matches) if(res == -1): self.firstPlayerWinning = False else: self.firstPlayerWinning = True return res def exploreMax(self, n): ''' `exploreMax` function tries to find if a player has possibilities to win the game Params : self -- the current instance of the game n -- a number of matches Return : -1 = lose or 0 = draw or +1 = win -- depends on the possibility to win of the player ''' self.exploreMaxCalls += 1 bestVal = -1 if(self.algorithmResFound): return 1 if(n<=0): self.algorithmResFound = True return 1 for i in range (1,4): if(self.algorithmResFound): break res = self.exploreMin(n-i) if(res > bestVal): bestVal = res if(bestVal == 1): self.algorithmResFound = True break return bestVal def exploreMin(self, n): ''' `exploreMin` function tries to find if a player has possibilities to win the game Params : self -- the current instance of the game n -- a number of matches Return : -1 = lose or 0 = draw or +1 = win -- depends on the possibility to win of the player ''' self.exploreMinCalls += 1 worstVal = 1 if(self.algorithmResFound): return -1 if(n<=0): self.algorithmResFound = True return -1 for i in range (1,4): if(self.algorithmResFound): break res = self.exploreMax(n-i) if(res < worstVal): worstVal = res if(worstVal == -1): self.algorithmResFound = True break return worstVal def __str__(self): ''' `__str__` function overrides the default function to get a custom display when printing the game object Params : self -- the current instance of the game Return : string -- contains all the game and algorithm values ''' content = ( "-----------------------\n" "Game and algorithm data\n" "-----------------------\n" "== Game data ==\n" f"Remaining matches : {self.matches}\n" f"Game state : {self.state}\n" f"Actual player : {self.playerTurn}\n" "== Algorithm data ==\n" f"exploreMax calls = {self.exploreMaxCalls}\n" f"exploreMin calls = {self.exploreMinCalls}\n" f"First player winning ? = {self.firstPlayerWinning}\n" ) return content game = Game(100) # Creating Nim game with 5 matches game.miniMax() # Checking if the player 1 is winning print(game) # Displays game and algorithm data