import math from copy import deepcopy from time import perf_counter from random import choice from GameState import GameState class GameController(object): def get_next_move(self, state): # when you get a new move, it is assumed that the game is not ended yet assert state.get_moves() class ABNode(object): # A class for Node related operations def __init__(self, state): self.Current = state if state.player == 1: self.CurrentScore = self.Current.score[2]-self.Current.score[1] elif state.player ==2: self.CurrentScore = self.Current.score[1]-self.Current.score[2] self.children = {} def update_score(self): if self.Current.player == 2: self.CurrentScore = self.Current.score[1]-self.Current.score[2] elif self.Current.player == 1: self.CurrentScore = self.Current.score[2]-self.Current.score[1] def Make(self, r,c,o): # Function for generating a child node lit=deepcopy(self.Current) self.children[(r,c,o)] = ABNode(lit) move=(r,c,o) self.children[(r,c,o)].Current.play_move(move) self.children[(r,c,o)].update_score() def Populate(self, r,c,o, Child): # Function for adding a node self.children[(r,c,o)] = Child def Draw(self): # function for drawing the board self.Current.Draw_mat() # A class for defining algorithms used (minimax and alpha-beta pruning) class AlphaBeta(object): def miniMax(self, State, Ply_num): # Function for the minimax algorithm State = deepcopy(State) start = ABNode(State) possiblemoves=State.get_moves() if len(possiblemoves) < 3: for x in possiblemoves: return x for x in possiblemoves: if len(possiblemoves) < 3: return x if (x[0],x[1],x[2]) not in start.children: start.Make(x[0],x[1],x[2]) # if Ply_num < 2: # return (i, j) Minimum_Score = 1000 r = 0 c = 0 o = "" for k, z in start.children.items(): Result = self.Maximum(z, Ply_num - 1, Minimum_Score) if Minimum_Score > Result: Minimum_Score = Result r = k[0] c = k[1] o = k[2] return (r,c,o) # Alpha-beta pruning function for taking care of Alpha values def Maximum(self, State, Ply_num, Alpha): if Ply_num == 0: return State.CurrentScore possiblemoves=State.Current.get_moves() for x in possiblemoves: if (x[0],x[1],x[2]) not in State.children: State.Make(x[0],x[1],x[2]) Maximum_Score = -1000 r = 0 c = 0 o="" for k, z in State.children.items(): Result = self.Minimum(z, Ply_num - 1, Maximum_Score) if Maximum_Score < Result: Maximum_Score = Result if Result > Alpha: return Result return Maximum_Score def Minimum(self, State, Ply_num, Beta): # Alpha-beta pruning function for taking care of Beta values if Ply_num == 0: return State.CurrentScore possiblemoves = State.Current.get_moves() for x in possiblemoves: if (x[0],x[1],x[2]) not in State.children: State.Make(x[0],x[1],x[2]) Minimum_Score = 1000 i = 0 j = 0 for k, z in State.children.items(): Result = self.Maximum(z, Ply_num - 1, Minimum_Score) if Minimum_Score > Result: Minimum_Score = Result if Result < Beta: return Result return Minimum_Score def __repr__(self): s="ABNode" return s