def minimax(newBoard, colour, oppo_colour, type):

        beta = math.inf
        bestVal = -math.inf
        bestState = None
        cord = Player.getSuccessors(newBoard, colour, "bs", type)

        count = 0
        MaxCount = 0
        #for every state call minimax on them
        for board in Player.getSuccessors(newBoard, colour, "boards", type):
            value = Player.min_value(board, 2, colour, oppo_colour, bestVal,
                                     beta, type)
            if (value > bestVal):
                MaxCount = count
                bestVal = value
                bestState = board

            count += 1
        #if its the placing phase place the piece on the best possible move
        if (type == "PP"):
            Board.placePiece(newBoard, cord[MaxCount][0], cord[MaxCount][1],
                             colour)
        #if its the moving phase move the piece to the best possible position
        if (type == "MP"):
            Board.movePiece(newBoard, cord[MaxCount][0], cord[MaxCount][1],
                            cord[MaxCount][2], cord[MaxCount][3])
        return cord[MaxCount]
    def action(self, turns):

        Game.removeKills(self.board)

        self.no_turns = turns
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.plasingPhase = False
            print("CHnaged to mving phase")

        if (self.plasingPhase):
            return (Player.minimax(self.board, self.team_colour,
                                   self.oppo_colour, "PP"))
            Board.printBoard(self.board)
            #Player.placing_phase(self.board, self.team_colour))

        else:
            print("My moving phase activated")
            out = Player.minimax(self.board, self.team_colour,
                                 self.oppo_colour, "MP")
            print(out)
            return (out[0], out[1]), (out[2], out[3])
            return Player.moving(self.board, self.team_colour)
    def update(self, action):
        #update number of turns
        self.no_turns=self.no_turns+1
        self.our_turns+=1
        #shrink board when number of turns achived
        if(self.no_turns==128):
            Game.shrinkBoard(self.board)
        if(self.no_turns==192):
            Game.shrinkBoard(self.board)
        if(self.our_turns==24):
            self.placingPhase=False

        #remove kill before anything
        Game.removeKills(self.board, self.team_colour, self.oppo_colour)
        if (action != None):
            #if its the placing phase
            if(self.placingPhase):
                #after placing the peice check for kills
                Board.placePiece(self.board,action[0],action[1],self.oppo_colour)
                Game.removeKillsAfterAction(self.board, action[0], action[1],
                                            self.team_colour, self.oppo_colour)
            else:
                #after moivng check for kills
                Board.movePiece(self.board,action[0][0], action[0][1],
                                                    action[1][0],action[1][1])
                Game.removeKillsAfterAction(self.board, action[1][0],
                                action[1][1], self.team_colour, self.oppo_colour)
 def PeiceAdvantage(state, colour, oppo_colour):
     eval=0
     for col in range (state.getMinColSize(),state.getMaxColSize()+1):
         for row in range (state.getMinRowSize(),state.getMaxRowSize()+1):
             if (Board.comaprePieceat(state,col,row, colour)):
                 eval+=1
             if (Board.comaprePieceat(state,col,row, oppo_colour)):
                 eval-=1
     return(eval)
    def evalFromCentre(state,colour,oppo_colour):
        evaluation=0
        totPeices=1
        for col in range(state.getMinColSize(),state.getMaxColSize()+1):
            for row in range(state.getMinRowSize(),state.getMaxRowSize()+1):
                if(Board.comaprePieceat(state,col,row,colour)):
                    totPeices+=1
                    evaluation-=abs(distance.euclidean((col,row),(3.5,3.5)))
                if(Board.comaprePieceat(state,col,row,oppo_colour)):
                    totPeices+=1
                    evaluation+=abs(distance.euclidean((col,row),(3.5,3.5)))

        return (evaluation/(totPeices*(state.getMaxColSize()-2)))
    def placingPhaseMoves(board, colour):
        moves = 0

        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1

        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1
        return moves
    def evalPartnerWarriorDiag(state,colour,oppo_colour):
        evaluation=0
        numberOfPeices=1
        for col in range(state.getMinColSize(),state.getMaxColSize()+1):
            for row in range(state.getMinRowSize(),state.getMaxRowSize()+1):
                if(Board.comaprePieceat(state,col,row,colour)):
                    numberOfPeices+=4
                    evaluation+=Evaluation.EvalDiag(state, col, row, colour)
                if(Board.comaprePieceat(state,col,row,oppo_colour)):
                    numberOfPeices+=4
                    evaluation-=Evaluation.EvalDiag(state, col, row, oppo_colour)



        return (evaluation/numberOfPeices)
 def piecesLeft(state, colour):
     count = 0
     for col in range(0, 8):
         for row in range(0, 8):
             if (Board.comaprePieceat(state, col, row, colour)):
                 count += 1
     return count
 def deathTrap(state, colour, oppo_colour):
     evaluation = 0
     for col in range(0, 8):
         for row in range(0, 8):
             if (Board.comaprePieceat(state, col, row, "E")):
                 evaluation += Evaluation.evalDeathTrap(
                     state, col, row, colour)
                 evaluation -= Evaluation.evalDeathTrap(
                     state, col, row, oppo_colour)
     return evaluation
    def evalPartnerWarriorDiag(state, colour, oppo_colour):
        evaluation = 0
        numberOfPeices = 1
        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(state, col, row, "W")):
                        numberOfPeices += 1
                        evaluation += Evaluation.EvalDiag(
                            state, col, row, colour)
        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(state, col, row, "B")):
                        numberOfPeices += 1
                        evaluation += Evaluation.EvalDiag(
                            state, col, row, colour)

        return (evaluation / numberOfPeices)
    def evalFromCentre(state, colour, oppo_colour):
        evaluation = 0
        totPeices = 0
        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(state, col, row, "W")):
                        totPeices += 1
                        evaluation += distance.euclidean((col, row),
                                                         (3.5, 3.5))

        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(state, col, row, "W")):
                        totPeices += 1
                        evaluation += distance.euclidean((col, row),
                                                         (3.5, 3.5))

        return evaluation
 def deathTrap(state,colour,oppo_colour):
     evaluation=0
     count=1
     for col in range(state.getMinColSize(),state.getMaxColSize()+1):
         for row in range(state.getMinRowSize(),state.getMaxRowSize()+1):
             if(Board.comaprePieceat(state,col,row,"E")):
                 count+=1
                 evaluation+=Evaluation.evalDeathTrap(state, col,row, colour)
                 evaluation-=Evaluation.evalDeathTrap(state, col,row,
                                                                 oppo_colour)
     return (evaluation/count)
    def moving(board, colour):

        for col in range(0, 8):
            for row in range(0, 8):
                if (Board.comaprePieceat(board, col, row, colour)):
                    if Game.freeUp(board, col, row):
                        Board.movePiece(board, col, row, col, row - 1)
                        return ((col, row), (col, row - 1))
                    if Game.freeDown(board, col, row):
                        Board.movePiece(board, col, row, col, row + 1)
                        return ((col, row), (col, row + 1))
                    if Game.freeRight(board, col, row):
                        Board.movePiece(board, col, row, col + 1, row)
                        return ((col, row), (col + 1, row))
                    if Game.freeLeft(board, col, row):
                        Board.movePiece(board, col, row, col - 1, row)
                        return ((col, row), (col - 1, row))
        return ()
def minimax(newBoard,colour,oppo_colour, type, evalWeights, cutOff):

    #initialize beta and other needed variables
    beta=math.inf
    bestVal=-math.inf
    bestState=None
    #get the first set of cordinates so we could return when we get the state
    #cord=getSuccessors(newBoard, colour,"bs",type, oppo_colour)

    count=0
    MaxCount=0
    #for every state call min_value on them
    #note:we are running 2 depth here itseldf
    cord, bds = getSuccessors(newBoard, colour,True, type, oppo_colour)
    for board in bds:
        #if we want depth 1
        if (cutOff==1):
            value=Evaluation.evalFinal(board,colour,oppo_colour, evalWeights)
        else:
            value = min_value(board, 2, colour, oppo_colour , bestVal, beta,
                                                    type, evalWeights, cutOff)
        #get the max value (max val)
        if (value > bestVal):
            MaxCount=count
            bestVal = value
            bestState = board

        count+=1
    #if its the placing phase place the piece on the best possible move
    if (type=="PP"):
        Board.placePiece(newBoard,cord[MaxCount][0], cord[MaxCount][1],colour)
    #if its the moving phase move the piece to the best possible position
    if (type=="MP"):
        if(len(cord)==0):
            return None
        Board.movePiece(newBoard,cord[MaxCount][0],cord[MaxCount][1],
                                            cord[MaxCount][2],cord[MaxCount][3])
    return cord[MaxCount]
    def distanceLine(state, colour, oppo_colour):
        numberOfPeices = 1
        eval = 0
        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(state, col, row, colour)):
                        numberOfPeices += 1
                        if (row > 1):
                            eval += (1 / (row - 1))
                        else:
                            eval += 0.75

        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(state, col, row, colour)):
                        numberOfPeices += 1
                        if (row < 6):
                            eval += (1 / (6 - row))
                        else:
                            eval += 0.75
        return (eval / numberOfPeices)
def countTotalMoves(board,colour):
    moves = 0
    for row in range(Board.getMinRowSize(board), Board.getMaxRowSize(board)+1):
        for col in range(Board.getMinColSize(board), Board.getMaxColSize(board)+1):
            if not(Board.comaprePieceat(board,col,row, "E")):
                if not(Board.comaprePieceat(board,col,row, colour)):
                    moves += countMoves(board,row, col)

    return moves
    def distanceLine(state, colour, oppo_colour):
        numberOfPeices=1
        eval=0
        if(colour=="W"):
            for col in range(state.getMinColSize(),state.getMaxColSize()+1):
                for row in range(state.getMinRowSize(),state.getMaxRowSize()+1):
                    if (Board.comaprePieceat(state,col,row, colour)):
                        numberOfPeices+=1
                        if(row>1):
                            eval+=(1/(row-1))
                        else:
                            eval+=0.75
                    if (Board.comaprePieceat(state,col,row, oppo_colour)):
                        numberOfPeices+=1
                        if(row<6):
                            eval-=(1/(6-row))
                        else:
                            eval-=0.75

        if(colour=="B"):
            for col in range(state.getMinColSize(),state.getMaxColSize()+1):
                for row in range(state.getMinRowSize(),state.getMaxRowSize()+1):
                    if (Board.comaprePieceat(state,col,row, colour)):
                        numberOfPeices+=1
                        if(row<6):
                            eval+=(1/(6-row))
                        else:
                            eval+=0.75
                    if (Board.comaprePieceat(state,col,row, oppo_colour)):
                        numberOfPeices+=1
                        if(row>1):
                            eval-=(1/(row-1))
                        else:
                            eval-=0.75

        return (eval/numberOfPeices)
 def mainFourSquares(state,colour, oppo_colour):
     eval=0
     if(Board.comaprePieceat(state,3,3,colour)):
         eval+=1
     if(Board.comaprePieceat(state,3,4,colour)):
         eval+=1
     if(Board.comaprePieceat(state,4,3,colour)):
         eval+=1
     if(Board.comaprePieceat(state,4,4,colour)):
         eval+=1
     if(Board.comaprePieceat(state,3,3,oppo_colour)):
         eval-=1
     if(Board.comaprePieceat(state,3,4,oppo_colour)):
         eval-=1
     if(Board.comaprePieceat(state,4,3,oppo_colour)):
         eval-=1
     if(Board.comaprePieceat(state,4,4,oppo_colour)):
         eval-=1
     return(eval/4)
    def placing_phase(board, colour):

        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        Board.placePiece(board, col, row, "W")
                        return (col, row)
        if (colour == "B"):
            for col in range(0, 8):
                for row in reversed(range(2, 8)):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        Board.placePiece(board, col, row, "B")
                        return (col, row)

        return ()
    def update(self, action):
        Board.printBoard(self.board)
        self.no_turns = self.no_turns + 1
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.placingPhase = False
            print("CHnaged to mving phase")

        Game.removeKills(self.board)
        print(self.no_turns)
        print(action)

        if (self.placingPhase):
            Board.placePiece(self.board, action[0], action[1],
                             self.oppo_colour)
        else:
            Board.movePiece(self.board, action[0][0], action[0][1],
                            action[1][0], action[1][1])
def getSuccessors(board, colour, needCord, type, oppo_colour):

    Successors=[]
    cord=[]
    #if its the placing phase then get states for that phase
    if (type=="PP"):

        #if you want the board as the output
        if(colour == "W"):
            for col in range (0,8):
                for row in range (0,6):
                    if (Board.comaprePieceat(board,col,row, "E")):
                        #make a copy of the board that will represent a new state
                        tempBoard=copy.deepcopy(board)
                        Board.placePiece(tempBoard,col,row,"W")
                        #check if after placing the piece there is something
                        # that can be eliminated from the board and remove it
                        #from the board
                        Game.removeKills(tempBoard, colour, oppo_colour)
                        Successors.append(tempBoard)
                        if (needCord):
                            cord.append((col, row))

        if(colour == "B"):
            for col in range (0,8):
                for row in range (2,8):
                    if (Board.comaprePieceat(board,col,row, "E")):
                        #make a copy of the board that will represent a new state
                        tempBoard=copy.deepcopy(board)
                        Board.placePiece(tempBoard,col,row,"B")
                        # check if after placing the piece there is something
                        # that can be eliminated from the board and remove it
                        #from the board
                        Game.removeKills(tempBoard, colour, oppo_colour)
                        Successors.append(tempBoard)
                        if (needCord):
                            cord.append((col, row))

    # if its in the moving phase then get states for that phase
    if (type=="MP"):
        #check all the possible moves peices of our colour can make and return states
        for row in range(Board.getMinRowSize(board), Board.getMaxRowSize(board)+1):
            for col in range(Board.getMinColSize(board), Board.getMaxColSize(board)+1):
                if (Board.comaprePieceat(board,col,row, colour )):
                    temp=checkMove(board,col, row)
                    for pos in temp:
                        #make a copy of the board that will represent a new state
                        tempBoard=copy.deepcopy(board)
                        #move the peice to the new location
                        Board.movePiece(tempBoard,col,row,pos[0],pos[1])
                        #remove kills
                        Game.removeKills(tempBoard, colour,oppo_colour )
                        Successors.append(tempBoard)
                        if (needCord):
                            cord.append((col,row,pos[0],pos[1]))

    return (cord,Successors)
class Player:

    global WHITE_PLAYER
    global BLACK_PLAYER
    WHITE_PLAYER="W"
    BLACK_PLAYER="B"

    board=Board()                           #our main board
    team_colour=None                        #our team colour
    oppo_colour=None                        #Opponent team colour
    placingPhase=True                       #if its still the placing phase
    no_turns=0                              #number of turns given by ref
    our_turns=-1                            #our count of turns
    attkStrat=None                          #attacking strategy
    defStrat=None                           #defending strategy
    godStrat=None                           #godMode strategy
    massacre=None                           #massacre strategy
    def __init__(self,colour):
        #initializing the team colour
        if (colour=="white"):
            self.team_colour=WHITE_PLAYER
            self.oppo_colour=BLACK_PLAYER
        else:
            self.team_colour=BLACK_PLAYER
            self.oppo_colour=WHITE_PLAYER
    
        #initialize the strategies
        self.attkStrat=strategies.StrategyHub(strategies.attackStrategy)
        self.defStrat=strategies.StrategyHub(strategies.defendStrategy)
        self.godModeStrat=strategies.StrategyHub(strategies.godMode)
        self.massacreStrat=strategies.StrategyHub(strategies.massacre)



###############################################################################

#DUMMY MOVES

#    #this function goes through the board and places the particular piece at

#the first empty position it finds
#    def placing_phase(board,colour):
#
#
#        if(colour == "W"):
#            for col in range (0,8):
#                for row in range (0,6):
#                    if (Board.comaprePieceat(board,col,row, "E")):
#                        Board.placePiece(board,col,row,"W")
#                        return(col,row)
#        if(colour == "B"):
#            for col in range (0,8):
#                for row in reversed(range (2,8)):
#                    if (Board.comaprePieceat(board,col,row, "E")):
#                        Board.placePiece(board,col,row,"B")
#                        return(col,row)
#
#        return();
#
#    def moving(board,colour):
#
#        for col in range(0,8):
#            for row in range(0,8):
#                if (Board.comaprePieceat(board,col,row, colour)):
#                    if Game.freeUp(board,col,row):
#                        Board.movePiece(board,col,row,col,row-1)
#                        return((col,row),(col,row-1))
#                    if Game.freeDown(board,col,row):
#                        Board.movePiece(board,col,row,col,row+1)
#                        return((col,row),(col,row+1))
#                    if Game.freeRight(board,col,row):
#                        Board.movePiece(board,col,row,col+1,row)
#                        return((col,row),(col+1,row))
#                    if Game.freeLeft(board,col,row):
#                        Board.movePiece(board,col,row,col-1,row)
#                        return((col,row),(col-1,row))
#        return()
###############################################################################








    def action(self, turns):
    
        #remove all the kills before starting
        Game.removeKills(self.board,  self.oppo_colour, self.team_colour)
        #update our number of turns
        self.no_turns=turns
        self.our_turns+=1
        #shrink the board if it reaches a set numbe rof turns
        if(self.no_turns==128):
            Game.shrinkBoard(self.board)
        if(self.no_turns==192):
            Game.shrinkBoard(self.board)

        #if we moved into the moving place, note it
        if(self.our_turns==24):
            self.placingPhase=False

        #if its the placing phase
        if (self.placingPhase):


            #if we have out peices in the 4 middle squares, excecute the god mode strategy
            if(Evaluation.mainFourSquares(self.board,self.team_colour,self.
                                                            oppo_colour)==1):
                out=self.godModeStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"PP",self.no_turns)
                #remove kills after placing
                Game.removeKillsAfterAction(self.board, out[0],out[1],
                                            self.oppo_colour, self.team_colour)
                return(out)



            tempAdvantage=Evaluation.PeiceAdvantage(self.board,self.team_colour,
                                                                self.oppo_colour)
            #if we have 5 more peices than the opponent, massacre!!!!!!!
            if(tempAdvantage>=5):
                out=self.massacreStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"PP",self.no_turns)
                #remove kills after placing
                Game.removeKillsAfterAction(self.board, out[0],out[1],
                                            self.oppo_colour, self.team_colour)
                return(out)



            #if we have 3 or less less peices than the opponent, excecute the
            #defend strategy
            if (tempAdvantage<=-3):
                out=self.defStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"PP",self.no_turns)
                #remove kills after placing
                Game.removeKillsAfterAction(self.board, out[0],out[1],
                                            self.oppo_colour, self.team_colour)
                return(out)
            else:
                #if not just atttaaackkkkkkk!!!!!
                out=self.attkStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"PP",self.no_turns)
                #remove kills after placing
                Game.removeKillsAfterAction(self.board, out[0],out[1],
                                            self.oppo_colour, self.team_colour)
                return(out)


        else: #if its moving phase
            #if we have out peices in the 4 middle squares, excecute
            #the god mode strategy
            if(Evaluation.mainFourSquares(self.board,self.team_colour,
                                                        self.oppo_colour)==1):
                out=self.godModeStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"MP",self.no_turns)
                if (out!=None):
                    #remove kills after the move
                    Game.removeKillsAfterAction(self.board, out[2],out[3],
                                            self.oppo_colour, self.team_colour)
                    return(out[0],out[1]),(out[2],out[3])
                return(None)


            #get our advantage
            tempAdvantage=Evaluation.PeiceAdvantage(self.board,
                                            self.team_colour,self.oppo_colour)
            #if we have 5 more peices than the opponent, massacre!!!!!!!
            if(tempAdvantage>=5):
                out=self.massacreStrat.execute(self.board,self.team_colour,
                                        self.oppo_colour,"MP", self.no_turns)
                Game.removeKillsAfterAction(self.board, out[2],out[3],
                                            self.oppo_colour, self.team_colour)
                return(out[0],out[1]),(out[2],out[3])
            #if we have 3 or less less peices than the opponent, excecute the
            #defend strategy
            if (tempAdvantage<=-3):
                out=self.defStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"MP", self.no_turns)
            else:
                #if not just atttaaackkkkkkk!!!!!
                out=self.attkStrat.execute(self.board,self.team_colour,
                                            self.oppo_colour,"MP", self.no_turns)
            if (out!=None):
                #remove kills after the move
                Game.removeKillsAfterAction(self.board, out[2],out[3],
                                            self.oppo_colour, self.team_colour)
                return(out[0],out[1]),(out[2],out[3])
            return(None)





    def update(self, action):
        #update number of turns
        self.no_turns=self.no_turns+1
        self.our_turns+=1
        #shrink board when number of turns achived
        if(self.no_turns==128):
            Game.shrinkBoard(self.board)
        if(self.no_turns==192):
            Game.shrinkBoard(self.board)
        if(self.our_turns==24):
            self.placingPhase=False

        #remove kill before anything
        Game.removeKills(self.board, self.team_colour, self.oppo_colour)
        if (action != None):
            #if its the placing phase
            if(self.placingPhase):
                #after placing the peice check for kills
                Board.placePiece(self.board,action[0],action[1],self.oppo_colour)
                Game.removeKillsAfterAction(self.board, action[0], action[1],
                                            self.team_colour, self.oppo_colour)
            else:
                #after moivng check for kills
                Board.movePiece(self.board,action[0][0], action[0][1],
                                                    action[1][0],action[1][1])
                Game.removeKillsAfterAction(self.board, action[1][0],
                                action[1][1], self.team_colour, self.oppo_colour)
def checkMove(board, col, row):
    possibleMoves = []

    # Check up if its free above and in the board range
    if (Board.validSquare(board,col,row-1) and Board.comaprePieceat(board,
                                                            col,row - 1, "E")):
        possibleMoves.append([col,row-1])

    # Check up for a jump over another piece above
    elif (Board.validSquare(board,col,row-2) and not (Board.comaprePieceat(board,
                col,row - 1, "E")) and Board.comaprePieceat(board,col,row-2,"E")):
        possibleMoves.append([col,row-2])

    # Check down if its free below and in the board range
    if (Board.validSquare(board,col,row+1) and Board.comaprePieceat(board,col,
                                                                row + 1, "E")):
        possibleMoves.append([col,row+1])
    # Check down for a jump below over another piece
    elif (((Board.validSquare(board,col,row+2)) and not(Board.comaprePieceat(
board,col,row - 1, "E"))) and (Board.comaprePieceat(board,col,row + 2, "E"))):
        possibleMoves.append([col,row+2])

    # check left if its free to the left and in the board range
    if (Board.validSquare(board,col-1,row) and Board.comaprePieceat(board,
                                                            col-1, row, "E")):
        possibleMoves.append([col-1,row])
    # check left for a jump over another piece to the left
    elif ((Board.validSquare(board,col-2,row) and not(Board.comaprePieceat(board,
                                                        col-1,row, "E"))) and
                (Board.comaprePieceat(board,col-2,row, "E"))):
        possibleMoves.append([col-2,row])

    # check right if its free to the right and in the board range
    if (Board.validSquare(board,col+1,row) and (Board.comaprePieceat(board,
                                                            col+1,row, "E"))):
        possibleMoves.append([col+1,row])
    # check right for a jump over another piece to the right
    elif ((Board.validSquare(board,col+2,row) and not(Board.comaprePieceat(board,
                                                            col+1,row, "E")))
          and (Board.comaprePieceat(board,col+2,row, "E"))):
        possibleMoves.append([col+2,row])
    #return the total number of moves available for that piece
    return possibleMoves
class Player:
    board = Board()
    team_colour = None
    oppo_colour = None
    plasingPhase = True
    no_turns = 0
    our_turns = -1

    def __init__(self, colour):
        if (colour == "white"):
            self.team_colour = "W"
            self.oppo_colour = "B"
        else:
            self.team_colour = "B"
            self.oppo_colour = "W"

########################################################

# countMoves calculates all the possible moves a single piece can make and
#sums it up

    def checkMove(board, col, row):
        possibleMoves = []

        # Check up if its free and in the board range
        if (Board.validSquare(board, col, row - 1)
                and Board.comaprePieceat(board, col, row - 1, "E")):
            possibleMoves.append([col, row - 1])

        # Check up for a jump over another piece
        elif (Board.validSquare(board, col, row - 2)
              and not (Board.comaprePieceat(board, col, row - 1, "E"))
              and Board.comaprePieceat(board, col, row - 2, "E")):
            possibleMoves.append([col, row - 2])

        # Check down if its free and in the board range
        if (Board.validSquare(board, col, row + 1)
                and Board.comaprePieceat(board, col, row + 1, "E")):
            possibleMoves.append([col, row + 1])
        # Check down for a jump over another piece
        elif (((Board.validSquare(board, col, row + 2))
               and not (Board.comaprePieceat(board, col, row - 1, "E")))
              and (Board.comaprePieceat(board, col, row + 2, "E"))):
            possibleMoves.append([col, row + 2])

            # check left if its free and in the board range
        if (Board.validSquare(board, col - 1, row)
                and Board.comaprePieceat(board, col - 1, row, "E")):
            possibleMoves.append([col - 1, row])
        # check left for a jump over another piece
        elif ((Board.validSquare(board, col - 2, row)
               and not (Board.comaprePieceat(board, col - 1, row, "E")))
              and (Board.comaprePieceat(board, col - 2, row, "E"))):
            possibleMoves.append([col - 2, row])

        # check right if its free and in the board range
        if (Board.validSquare(board, col + 1, row)
                and (Board.comaprePieceat(board, col + 1, row, "E"))):
            possibleMoves.append([col + 1, row])
        # check right for a jump over another piece
        elif ((Board.validSquare(board, col + 2, row)
               and not (Board.comaprePieceat(board, col + 1, row, "E")))
              and (Board.comaprePieceat(board, col + 2, row, "E"))):
            possibleMoves.append([col + 2, row])
        #return the total number of moves available for that piece
        return possibleMoves

    # countTotalMoves iterates through the board and sums up the total number
    #of possible moves for each of the players
    def countTotalMoves(board, colour):
        moves = 0
        for row in range(Board.getMinRowSize(board),
                         Board.getMaxRowSize(board) + 1):
            for col in range(Board.getMinColSize(board),
                             Board.getMaxColSize(board) + 1):
                if not (Board.comaprePieceat(board, col, row, "E")):
                    if not (Board.comaprePieceat(board, col, row, colour)):
                        moves += Player.countMoves(board, row, col)

        return moves

########################################################

########################################################
#total counts in a placing phase

    def placingPhaseMoves(board, colour):
        moves = 0

        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1

        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1
        return moves

########################################################

#gets a successors of the board

    def getSuccessors(board, colour, output, type):

        Successors = []
        #if its in the placing phase then get states for that phase
        if (type == "PP"):

            #if you want the board as the output
            if (output == "boards"):
                if (colour == "W"):
                    for col in range(0, 8):
                        for row in range(0, 6):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.placePiece(tempBoard, col, row, "W")
                                Game.removeKills(
                                    tempBoard
                                )  # check if after placing the piece there is something
                                # that can be eliminated from the board and remove it from the board
                                Successors.append(tempBoard)

                if (colour == "B"):
                    for col in range(0, 8):
                        for row in range(2, 8):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.placePiece(tempBoard, col, row, "B")
                                Game.removeKills(
                                    tempBoard
                                )  # check if after placing the piece there is something
                                # that can be eliminated from the board and remove it from the board
                                Successors.append(tempBoard)
            #if you want the output as coordinates
            else:
                if (colour == "W"):
                    for col in range(0, 8):
                        for row in range(0, 6):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                Successors.append((col, row))

                if (colour == "B"):
                    for col in range(0, 8):
                        for row in range(2, 8):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                Successors.append((col, row))

        # if its in the moving phase then get states for that phase
        if (type == "MP"):
            if (output == "boards"):
                for row in range(Board.getMinRowSize(board),
                                 Board.getMaxRowSize(board) + 1):
                    for col in range(Board.getMinColSize(board),
                                     Board.getMaxColSize(board) + 1):
                        if (Board.comaprePieceat(board, col, row, colour)):
                            temp = Player.checkMove(board, col, row)
                            for pos in temp:
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.movePiece(tempBoard, col, row, pos[0],
                                                pos[1])
                                Game.removeKills(tempBoard)
                                Successors.append(tempBoard)

            else:
                for row in range(Board.getMinRowSize(board),
                                 Board.getMaxRowSize(board) + 1):
                    for col in range(Board.getMinColSize(board),
                                     Board.getMaxColSize(board) + 1):
                        if (Board.comaprePieceat(board, col, row, colour)):
                            temp = Player.checkMove(board, col, row)
                            for pos in temp:
                                Successors.append((col, row, pos[0], pos[1]))

        return Successors

    def minimax(newBoard, colour, oppo_colour, type):

        beta = math.inf
        bestVal = -math.inf
        bestState = None
        cord = Player.getSuccessors(newBoard, colour, "bs", type)

        count = 0
        MaxCount = 0
        #for every state call minimax on them
        for board in Player.getSuccessors(newBoard, colour, "boards", type):
            value = Player.min_value(board, 2, colour, oppo_colour, bestVal,
                                     beta, type)
            if (value > bestVal):
                MaxCount = count
                bestVal = value
                bestState = board

            count += 1
        #if its the placing phase place the piece on the best possible move
        if (type == "PP"):
            Board.placePiece(newBoard, cord[MaxCount][0], cord[MaxCount][1],
                             colour)
        #if its the moving phase move the piece to the best possible position
        if (type == "MP"):
            Board.movePiece(newBoard, cord[MaxCount][0], cord[MaxCount][1],
                            cord[MaxCount][2], cord[MaxCount][3])
        return cord[MaxCount]

    def max_value(newBoard, depth, colour, oppo_colour, alpha, beta, type):
        #if the depth reaches 2 then start evaluating each state
        if (depth == 3):
            if (type == "PP"):
                return Evaluation.eval1(newBoard, colour, oppo_colour)
            else:
                return Evaluation.eval2(newBoard, colour, oppo_colour)
        v = -math.inf

        #for each of the states from the lower depth get the max value
        for b in Player.getSuccessors(newBoard, colour, "boards", type):

            v = max(
                v,
                Player.min_value(b, depth + 1, colour, oppo_colour, alpha,
                                 beta, type))

            if (v > beta):
                return v
            alpha = max(alpha, v)
        return v

    def min_value(newBoard, depth, colour, oppo_colour, alpha, beta, type):
        # if the depth reaches 2 then start evaluating each state
        if (depth == 3):
            if (type == "PP"):
                return Evaluation.eval1(newBoard, colour, oppo_colour)
            else:
                return Evaluation.eval2(newBoard, colour, oppo_colour)

        v = math.inf
        # for each of the states from the lower depth get the min value
        for b in Player.getSuccessors(newBoard, oppo_colour, "boards", type):

            v = min(
                v,
                Player.max_value(b, depth + 1, colour, oppo_colour, alpha,
                                 beta, type))
            if (v < alpha):
                return v
            beta = min(beta, v)
        return v

#action= argmax(getSuccessorsMP(newboard, colour), lambda(newBoard): min_value(newBoard))

#this function goes through the board and places the particular piece at the first empty position it finds

    def placing_phase(board, colour):

        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        Board.placePiece(board, col, row, "W")
                        return (col, row)
        if (colour == "B"):
            for col in range(0, 8):
                for row in reversed(range(2, 8)):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        Board.placePiece(board, col, row, "B")
                        return (col, row)

        return ()

    def moving(board, colour):

        for col in range(0, 8):
            for row in range(0, 8):
                if (Board.comaprePieceat(board, col, row, colour)):
                    if Game.freeUp(board, col, row):
                        Board.movePiece(board, col, row, col, row - 1)
                        return ((col, row), (col, row - 1))
                    if Game.freeDown(board, col, row):
                        Board.movePiece(board, col, row, col, row + 1)
                        return ((col, row), (col, row + 1))
                    if Game.freeRight(board, col, row):
                        Board.movePiece(board, col, row, col + 1, row)
                        return ((col, row), (col + 1, row))
                    if Game.freeLeft(board, col, row):
                        Board.movePiece(board, col, row, col - 1, row)
                        return ((col, row), (col - 1, row))
        return ()

    def action(self, turns):

        Game.removeKills(self.board)

        self.no_turns = turns
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.plasingPhase = False
            print("CHnaged to mving phase")

        if (self.plasingPhase):
            return (Player.minimax(self.board, self.team_colour,
                                   self.oppo_colour, "PP"))
            Board.printBoard(self.board)
            #Player.placing_phase(self.board, self.team_colour))

        else:
            print("My moving phase activated")
            out = Player.minimax(self.board, self.team_colour,
                                 self.oppo_colour, "MP")
            print(out)
            return (out[0], out[1]), (out[2], out[3])
            return Player.moving(self.board, self.team_colour)

    def update(self, action):
        Board.printBoard(self.board)
        self.no_turns = self.no_turns + 1
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.plasingPhase = False
            print("CHnaged to mving phase")

        Game.removeKills(self.board)
        print(self.no_turns)
        print(action)

        if (self.plasingPhase):
            Board.placePiece(self.board, action[0], action[1],
                             self.oppo_colour)
        else:
            Board.movePiece(self.board, action[0][0], action[0][1],
                            action[1][0], action[1][1])
    def getSuccessors(board, colour, output, type):

        Successors = []
        #if its in the placing phase then get states for that phase
        if (type == "PP"):

            #if you want the board as the output
            if (output == "boards"):
                if (colour == "W"):
                    for col in range(0, 8):
                        for row in range(0, 6):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.placePiece(tempBoard, col, row, "W")
                                Game.removeKills(
                                    tempBoard
                                )  # check if after placing the piece there is something
                                # that can be eliminated from the board and remove it from the board
                                Successors.append(tempBoard)

                if (colour == "B"):
                    for col in range(0, 8):
                        for row in range(2, 8):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.placePiece(tempBoard, col, row, "B")
                                Game.removeKills(
                                    tempBoard
                                )  # check if after placing the piece there is something
                                # that can be eliminated from the board and remove it from the board
                                Successors.append(tempBoard)
            #if you want the output as coordinates
            else:
                if (colour == "W"):
                    for col in range(0, 8):
                        for row in range(0, 6):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                Successors.append((col, row))

                if (colour == "B"):
                    for col in range(0, 8):
                        for row in range(2, 8):
                            if (Board.comaprePieceat(board, col, row, "E")):
                                Successors.append((col, row))

        # if its in the moving phase then get states for that phase
        if (type == "MP"):
            if (output == "boards"):
                for row in range(Board.getMinRowSize(board),
                                 Board.getMaxRowSize(board) + 1):
                    for col in range(Board.getMinColSize(board),
                                     Board.getMaxColSize(board) + 1):
                        if (Board.comaprePieceat(board, col, row, colour)):
                            temp = Player.checkMove(board, col, row)
                            for pos in temp:
                                tempBoard = copy.deepcopy(
                                    board
                                )  #make a copy of the board that will represent a new state
                                Board.movePiece(tempBoard, col, row, pos[0],
                                                pos[1])
                                Game.removeKills(tempBoard)
                                Successors.append(tempBoard)

            else:
                for row in range(Board.getMinRowSize(board),
                                 Board.getMaxRowSize(board) + 1):
                    for col in range(Board.getMinColSize(board),
                                     Board.getMaxColSize(board) + 1):
                        if (Board.comaprePieceat(board, col, row, colour)):
                            temp = Player.checkMove(board, col, row)
                            for pos in temp:
                                Successors.append((col, row, pos[0], pos[1]))

        return Successors
 def checkDiagRightDown(board,col,row, colour):
     if (Board.validSquare(board,col+1,row+1) and (Board.comaprePieceat(
                                                 board,col+1,row+1, colour))):
         return 1
     return 0
 def checkDiagLeftUp(board,col,row, colour):
     if (Board.validSquare(board,col-1,row-1) and (Board.comaprePieceat(
                                             board,col-1,row-1, colour))):
         return 1
     return 0
class Player:
    board = Board()
    team_colour = None
    oppo_colour = None
    placingPhase = True
    no_turns = 0
    our_turns = -1
    attkStrat = None
    defStrat = None

    def __init__(self, colour):
        if (colour == "white"):
            self.team_colour = "W"
            self.oppo_colour = "B"
        else:
            self.team_colour = "B"
            self.oppo_colour = "W"

        self.attkStrat = strategies.StrategyHub(strategies.attackStrategy)
        self.defStrat = strategies.StrategyHub(strategies.defendStrategy)

    def placingPhaseMoves(board, colour):
        moves = 0

        if (colour == "W"):
            for col in range(0, 8):
                for row in range(0, 6):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1

        if (colour == "B"):
            for col in range(0, 8):
                for row in range(2, 8):
                    if (Board.comaprePieceat(board, col, row, "E")):
                        moves += 1
        return moves

###############################################################################

#DUMMY MOVES

#    #this function goes through the board and places the particular piece at the first empty position it finds
#    def placing_phase(board,colour):
#
#
#        if(colour == "W"):
#            for col in range (0,8):
#                for row in range (0,6):
#                    if (Board.comaprePieceat(board,col,row, "E")):
#                        Board.placePiece(board,col,row,"W")
#                        return(col,row)
#        if(colour == "B"):
#            for col in range (0,8):
#                for row in reversed(range (2,8)):
#                    if (Board.comaprePieceat(board,col,row, "E")):
#                        Board.placePiece(board,col,row,"B")
#                        return(col,row)
#
#        return();
#
#    def moving(board,colour):
#
#        for col in range(0,8):
#            for row in range(0,8):
#                if (Board.comaprePieceat(board,col,row, colour)):
#                    if Game.freeUp(board,col,row):
#                        Board.movePiece(board,col,row,col,row-1)
#                        return((col,row),(col,row-1))
#                    if Game.freeDown(board,col,row):
#                        Board.movePiece(board,col,row,col,row+1)
#                        return((col,row),(col,row+1))
#                    if Game.freeRight(board,col,row):
#                        Board.movePiece(board,col,row,col+1,row)
#                        return((col,row),(col+1,row))
#                    if Game.freeLeft(board,col,row):
#                        Board.movePiece(board,col,row,col-1,row)
#                        return((col,row),(col-1,row))
#        return()
###############################################################################

    def action(self, turns):

        Game.removeKills(self.board)

        self.no_turns = turns
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.placingPhase = False
            print("CHnaged to mving phase")

        if (self.placingPhase):
            return (self.attkStrat.execute(self.board, self.team_colour,
                                           self.oppo_colour, "PP"))

        else:
            print("My moving phase activated")
            out = self.attkStrat.execute(self.board, self.team_colour,
                                         self.oppo_colour, "MP")
            return (out[0], out[1]), (out[2], out[3])

    def update(self, action):
        Board.printBoard(self.board)
        self.no_turns = self.no_turns + 1
        self.our_turns += 1
        if (self.no_turns == 128):
            Game.shrinkBoard(self.board)
        if (self.no_turns == 192):
            Game.shrinkBoard(self.board)
        if (self.our_turns == 24):
            self.placingPhase = False
            print("CHnaged to mving phase")

        Game.removeKills(self.board)
        print(self.no_turns)
        print(action)

        if (self.placingPhase):
            Board.placePiece(self.board, action[0], action[1],
                             self.oppo_colour)
        else:
            Board.movePiece(self.board, action[0][0], action[0][1],
                            action[1][0], action[1][1])