Ridwanul_Haque

Mancala Player

Dec 18th, 2021
1,067
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.81 KB | None | 0 0
  1. from Board import Board
  2.  
  3. alpha_beta_pruning = 1
  4. human = 2
  5. HEURISTIC1 = 3
  6. HEURISTIC2 = 4
  7. HEURISTIC3 = 5
  8. HEURISTIC4 = 6
  9. bin_quantity = 6
  10. initialStone = 4
  11. inf = 1e9
  12. win = 1e4
  13.  
  14. class Player(object):
  15.     def __init__(self, playerNo, playerType, HEURISTICNo, W1, W2, W3, W4, depth):
  16.         self.tempBoard = Board()
  17.         self.playerType = playerType
  18.         self.playerNo = playerNo
  19.         self.turn = -1
  20.  
  21.         # if alpha-beta pruning is used then these are required
  22.         self.HEURISTICNo = HEURISTICNo
  23.         self.W1 = W1
  24.         self.W2 = W2
  25.         self.W3 = W3
  26.         self.W4 = W4
  27.         self.depth = depth
  28.  
  29.         # additional move
  30.         self.additionalMoveEarned = None
  31.  
  32.         self.otherPlayer = 1
  33.         if playerNo == 1:
  34.             self.otherPlayer = 2
  35.  
  36.     def getNextMove(self, board):
  37.         if self.playerType == human:
  38.             return self.__getHumanMove(board)
  39.  
  40.         elif self.playerType == alpha_beta_pruning:
  41.             self.additionalMoveEarned = 0
  42.             bn = self.__MiniMax(board, self.depth, True, -inf, inf)
  43.             print("AI selected:", bn, "\n")
  44.             return bn
  45.  
  46.         else:
  47.             print("invalid player type")
  48.             return 1
  49.  
  50.     # minimax algorithm using alpha-beta pruning
  51.     def __MiniMax(self, board, depth, isMax, alpha, beta):
  52.         # if the game is over
  53.         if board.gameOver(False):
  54.             if board.checkWinner() == self.playerNo:
  55.                 return win
  56.             elif board.checkWinner() == self.otherPlayer:
  57.                 return -win
  58.             else:
  59.                 return self.__evaluateNode(board)
  60.  
  61.         if depth == 0:
  62.             return self.__evaluateNode(board)
  63.  
  64.         # save a copy of the board
  65.         myBoard = Board()
  66.         myBoard.copyBoardDetail(board)
  67.  
  68.         if isMax:
  69.             best_value = -inf
  70.             successor = -1
  71.             for i in range(1, bin_quantity + 1):
  72.                 if board.bin[self.playerNo][i] > 0:
  73.                     temp_bn = board.updateBoard(self.playerNo, i)
  74.  
  75.                     # if additional turn achieved
  76.                     if temp_bn == self.playerNo:
  77.                         self.additionalMoveEarned += 1
  78.                         curr_value = self.__MiniMax(board, depth - 1, True, alpha, beta)
  79.                         self.additionalMoveEarned -= 1
  80.                     else:
  81.                         curr_value = self.__MiniMax(board, depth - 1, False, alpha, beta)
  82.  
  83.                     # we do this only in the maximizer because the root is "Max"
  84.                     # the root only needs to decide the successor
  85.                     if curr_value > best_value:
  86.                         best_value = curr_value
  87.                         successor = i
  88.  
  89.                     alpha = max(best_value, alpha)
  90.                     if beta <= alpha:
  91.                         break
  92.  
  93.                     board.copyBoardDetail(myBoard)  # restore original board
  94.  
  95.             # if root then return the successor
  96.             if self.depth == depth:
  97.                 return successor
  98.  
  99.             return best_value
  100.  
  101.         else:
  102.             best_value = inf
  103.             for i in range(1, bin_quantity + 1):
  104.                 if board.bin[self.otherPlayer][i] > 0:
  105.                     # min is the opponent aka other-player
  106.                     temp_bn = board.updateBoard(self.otherPlayer, i)
  107.  
  108.                     # if other player gets an additional turn
  109.                     if temp_bn == self.otherPlayer:
  110.                         self.additionalMoveEarned -= 1
  111.                         curr_value = self.__MiniMax(board, depth - 1, False, alpha, beta)
  112.                         self.additionalMoveEarned += 1
  113.                     else:
  114.                         curr_value = self.__MiniMax(board, depth - 1, True, alpha, beta)
  115.  
  116.                     best_value = min(best_value, curr_value)
  117.                     beta = min(best_value, beta)
  118.  
  119.                     if beta <= alpha:
  120.                         break
  121.  
  122.                     board.copyBoardDetail(myBoard)  # restore original board
  123.             return best_value
  124.  
  125.     def __evaluateNode(self, board):
  126.         if self.HEURISTICNo == HEURISTIC1:
  127.             return self.__HEURISTICOne(board)
  128.         elif self.HEURISTICNo == HEURISTIC2:
  129.             return self.__HEURISTICTwo(board)
  130.         elif self.HEURISTICNo == HEURISTIC3:
  131.             return self.__HEURISTICThree(board)
  132.         elif self.HEURISTICNo == HEURISTIC4:
  133.             return self.__HEURISTICFour(board)
  134.  
  135.     def __getHumanMove(self, board):
  136.         while True:
  137.             bn = int(input())
  138.  
  139.             if bn <= 0 or bn > bin_quantity:
  140.                 print("input out of range")
  141.             elif board.bin[self.playerNo][bn] == 0:
  142.                 print("empty bin :", bn)
  143.             else:
  144.                 return bn
  145.  
  146.     def __HEURISTICOne(self, board):
  147.         return board.storage[self.playerNo] - board.storage[self.otherPlayer]
  148.  
  149.     def __HEURISTICTwo(self, board):
  150.         stones_on_my_side = sum(board.bin[self.playerNo][1:bin_quantity + 1])
  151.         stones_on_opponents_side = sum(board.bin[self.otherPlayer][1:bin_quantity + 1])
  152.         stones_in_my_storage = board.storage[self.playerNo]
  153.         stones_in_opponents_storage = board.storage[self.otherPlayer]
  154.  
  155.         ret = self.W1 * (stones_in_my_storage - stones_in_opponents_storage) + \
  156.               self.W2 * (stones_on_my_side - stones_on_opponents_side)
  157.  
  158.         return ret
  159.  
  160.     def __HEURISTICThree(self, board):
  161.         additional_move_earned = self.additionalMoveEarned
  162.         return self.__HEURISTICTwo(board) + self.W3 * additional_move_earned
  163.  
  164.     def __HEURISTICFour(self, board):
  165.         stones_captured = board.storage[self.playerNo] - self.tempBoard.storage[self.playerNo]
  166.         return self.__HEURISTICThree(board) + self.W4 * stones_captured
  167.  
Advertisement
Add Comment
Please, Sign In to add comment