2023-07-28 19:34:53 +01:00
|
|
|
import random
|
|
|
|
from math import inf
|
|
|
|
|
|
|
|
from utilities.constants import GREEN, WHITE
|
2023-09-18 20:11:39 +01:00
|
|
|
from utilities.gameManager import GameManager
|
2023-07-28 19:34:53 +01:00
|
|
|
|
|
|
|
|
2023-08-22 16:31:16 +01:00
|
|
|
class MiniMax:
|
2023-07-28 19:34:53 +01:00
|
|
|
|
2023-09-18 20:11:39 +01:00
|
|
|
def AI(self, depth: int, maxPlayer: int, gameManager: GameManager) -> tuple:
|
|
|
|
"""
|
|
|
|
The minimax algorithm
|
|
|
|
:param depth: How deep the algorithm should go
|
|
|
|
:param maxPlayer: The current player
|
|
|
|
:param gameManager: The game manager
|
|
|
|
:return: the best evaluation and board
|
|
|
|
"""
|
2023-08-22 16:31:16 +01:00
|
|
|
if depth == 0 or gameManager.board.winner() is not None:
|
|
|
|
return gameManager.board.scoreOfTheBoard(), gameManager.board
|
2023-07-28 19:34:53 +01:00
|
|
|
|
2023-08-22 16:31:16 +01:00
|
|
|
if type(maxPlayer) == int:
|
2023-07-28 19:34:53 +01:00
|
|
|
maxEval = -inf
|
|
|
|
bestMove = None
|
2023-08-22 16:31:16 +01:00
|
|
|
for move in gameManager.board.getAllMoves(maxPlayer):
|
|
|
|
evaluation = self.AI(depth - 1, False, gameManager)[0]
|
2023-07-28 19:34:53 +01:00
|
|
|
maxEval = max(maxEval, evaluation)
|
|
|
|
if maxEval > evaluation:
|
|
|
|
bestMove = move
|
|
|
|
if maxEval == evaluation:
|
2023-08-22 16:31:16 +01:00
|
|
|
# bestMove = move
|
2023-07-28 19:34:53 +01:00
|
|
|
bestMove = bestMove if random.choice([True, False]) else move
|
|
|
|
return maxEval, bestMove
|
|
|
|
else:
|
|
|
|
minEval = inf
|
|
|
|
bestMove = None
|
|
|
|
colour = WHITE if gameManager.turn == GREEN else GREEN
|
2023-08-22 16:31:16 +01:00
|
|
|
for move in gameManager.board.getAllMoves(colour):
|
|
|
|
evaluation = self.AI(depth - 1, True, gameManager)[0]
|
2023-07-28 19:34:53 +01:00
|
|
|
minEval = min(minEval, evaluation)
|
|
|
|
if minEval < evaluation:
|
|
|
|
bestMove = move
|
|
|
|
if minEval == evaluation:
|
2023-08-22 16:31:16 +01:00
|
|
|
# bestMove = move
|
2023-07-28 19:34:53 +01:00
|
|
|
bestMove = bestMove if random.choice([True, False]) else move
|
|
|
|
|
|
|
|
return minEval, bestMove
|