private MoveEvalScore minimax(BoardMove node, int depth, int hole)
  {
    //if depth = 0 or node is a terminal node
    if(depth == 0 || Kalah.gameOver(node.getBoard()))
    {	
    	//heuristic value of node
      return new MoveEvalScore(hole,evalFunc.compareScoringWells(node, initialDepth % 2 == 0 ?node.getNextSide(): node.getNextSide().opposite(), hole));
    }
    	
    	//if side == ourSide, initialise bestValue to Integer.MIN_VALUE as we want to find maximum and vice versa.	
      MoveEvalScore bestValue = new MoveEvalScore(hole,node.getNextSide().equals(ourSide)?Integer.MIN_VALUE:Integer.MAX_VALUE);

      //for each child node
      int numHoles = node.getBoard().getNoOfHoles();
      
      for(int i = 1; i <= numHoles; i++)    //wells start a 1 (0 = scoring well)
      {
        //if there are seeds in well, then make a clone
        if(node.getBoard().getSeeds(node.getNextSide(), i) > 0)
        {
          try
          {
            Board child = node.getBoard().clone();
            //make the move
            Move move = new Move(node.getNextSide(), i);
            BoardMove boardMove = makeMove(child, move);
            
            child = boardMove.getBoard();             
            
            //recursively call minimax on child
            MoveEvalScore val = minimax(boardMove, depth - 1, i);
            
            //if side == ourSide, find maximum, else find minimum.
            bestValue = node.getNextSide().equals(ourSide)?max(bestValue, val):min(bestValue, val);
          }
          catch(Exception e)
          {
            display(e.toString());
          }
        }
      }
    	//display("jksdfhsminimax(" + node.toString() + ", " + depth + ", " + side.toString() + ", " + hole + ", " + prevHole + ")");
    	//display(depth + "\nthis move: " + hole + ", prev move: " + prevHole + "\nBest score = " + bestValue.getScore() + "\nMove: " + bestValue.getMove());
    	

    	if(node.getBoard().equals(root))  //if we are returning back to Main, then return best move and the hole it came from.
    	{
    		return bestValue;
    	}
    	else	//return best score and current hole.
    	{
    		return new MoveEvalScore(hole, bestValue.getScore());
    	}
      
  }