From fae51028b1f4f3b1b528a4e515f3b24b63873134 Mon Sep 17 00:00:00 2001
From: P Gautam <92343715+PGautam27@users.noreply.github.com>
Date: Fri, 7 Oct 2022 19:09:56 +0530
Subject: [PATCH] Added miniMax

---
 scripts/MiniMaxAlgo/player.py | 43 +++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/scripts/MiniMaxAlgo/player.py b/scripts/MiniMaxAlgo/player.py
index 2ffe8cc..34e997c 100644
--- a/scripts/MiniMaxAlgo/player.py
+++ b/scripts/MiniMaxAlgo/player.py
@@ -36,3 +36,46 @@ class RandomComputerPlayer(Player):
     def get_move(self, game):
         square = random.choice(game.available_moves())
         return square
+    
+class SmartComputerPlayer(Player):
+    def __init__(self, letter):
+        super().__init__(letter)
+
+    def get_move(self, game):
+        if len(game.available_moves()) == 9:
+            square = random.choice(game.available_moves())
+        else:
+            square = self.minimax(game, self.letter)['position']
+        return square
+
+    def minimax(self, state, player):
+        max_player = self.letter  # yourself
+        other_player = 'O' if player == 'X' else 'X'
+
+        # first we want to check if the previous move is a winner
+        if state.current_winner == other_player:
+            return {'position': None, 'score': 1 * (state.num_empty_squares() + 1) if other_player == max_player else -1 * (
+                        state.num_empty_squares() + 1)}
+        elif not state.empty_squares():
+            return {'position': None, 'score': 0}
+
+        if player == max_player:
+            best = {'position': None, 'score': -math.inf}  # each score should maximize
+        else:
+            best = {'position': None, 'score': math.inf}  # each score should minimize
+        for possible_move in state.available_moves():
+            state.make_move(possible_move, player)
+            sim_score = self.minimax(state, other_player)  # simulate a game after making that move
+
+            # undo move
+            state.board[possible_move] = ' '
+            state.current_winner = None
+            sim_score['position'] = possible_move  # this represents the move optimal next move
+
+            if player == max_player:  # X is max player
+                if sim_score['score'] > best['score']:
+                    best = sim_score
+            else:
+                if sim_score['score'] < best['score']:
+                    best = sim_score
+        return best