def _min_value(self, state: OthelloBoard):
     if not(state.has_legal_moves_remaining(self.symbol)) and not(state.has_legal_moves_remaining(self.oppSym)):
         return self._utility(state)
     value = float('inf')
     actions = list(state.get_legal_moves(self.oppSym))
     for a in actions:
         clone = state.cloneOBoard() #preserve initial board
         clone.play_move(a[0], a[1], self.oppSym) #generate successor
         value = min(value, self._max_value(clone))
     return value
 def _minimax_decision(self, state: OthelloBoard):
     actions = list(state.get_legal_moves(self.symbol))
     value = float("-inf")
     champ_action = actions[0]
     for a in actions:
         clone = state.cloneOBoard() #preserve initial board
         clone.play_move(a[0], a[1], self.symbol) #generate successor
         min_val = self._min_value(clone)
         if(min_val > value): #choose action with max value
             champ_action = a
     return champ_action