// Adds the position and it's estimated utility to the table.
  // If the position is already in the table (which will happen sometimes), It will either update.
  public void addPositionToListOfAnalysedPositions(
      int key[], boolean isDarkPlayerCurrentTurn, int curdepth, double utility) {

    boolean alreadyDidPos = false;
    AnalysedPosition alreadyAnalysedPos = null;

    // check if the position has been inserted after doing the recursion:
    if (viewedPos != null) {
      alreadyAnalysedPos = viewedPos.search(key);
      if (alreadyAnalysedPos != null) {
        alreadyDidPos = true;
      }
    }

    // If the position is not already done:
    if (alreadyDidPos == false) {
      AnalysedPosition pos = new AnalysedPosition(curdepth, isDarkPlayerCurrentTurn, utility, key);
      viewedPos = BalancedSearchTree.addValueToTree(viewedPos, pos);

      // FOR TEST PURPOSES
      numPosRecorded++;
      // TESTING SLOW
      if (debug) {
        sanityCheckNumNodes();
        viewedPos.sanityCheckSorted();
      }
      // END TESTING

      // if we only need to update:
    } else {
      alreadyAnalysedPos.updatePositionWithImprovedCalculation(curdepth, utility);
    }
  }
  public Double getUtilityIfAlreadyFound(int key[], int curdepth) {

    if (viewedPos != null) {
      AnalysedPosition alreadyAnalysedPos = viewedPos.search(key);
      if (alreadyAnalysedPos != null && alreadyAnalysedPos.getDepth() >= curdepth) {
        return new Double(alreadyAnalysedPos.getUtility());
      }
    }
    return null;
  }
 // testing: MAKE SURE THAT THE KEY STAYS THE SAME!!!
 public void sanityTestKeyBeforeAndAfter(
     CheckersSetup setup, boolean isDarkPlayerCurrentTurn, int key[]) {
   int key2[] = AnalysedPosition.makeKey(setup, isDarkPlayerCurrentTurn);
   int compare = BalancedSearchTree.compare(key, key2);
   if (compare != 0) {
     System.out.println("ERROR: the board changes through the getEstUtilityOfPosition function.");
     System.exit(1);
   }
 }
 // testing: make sure that the position didn't suddenly get on the list.
 public void sanityTestPositionDidntDissapearOffTree(
     AnalysedPosition alreadyAnalysedPos, int key[], boolean alreadyDidPos, int curdepth) {
   // note: this should not happen within this function.
   if (viewedPos != null) {
     alreadyAnalysedPos = viewedPos.search(key);
     if (alreadyAnalysedPos != null && alreadyDidPos == false) {
       if (alreadyAnalysedPos.getDepth() >= curdepth) {
         System.out.println("ERROR: Position should have been viewable earlier");
         System.exit(1);
       }
     }
   }
 }
  // pre: this position MUST be at the beginning of a turn.
  // post: returns the utility of the checkers position for whoever's turn it happens to be.
  public double getEstUtilityOfPosition(
      CheckersSetup setup, boolean isDarkPlayerCurrentTurn, int curdepth) {
    double ret;

    // this key identifies the setup of the board and who's turn it is in 3 numbers:
    int key[] = AnalysedPosition.makeKey(setup, isDarkPlayerCurrentTurn);

    // ret pos!!!!
    // Check to see if the position has already been analysed
    Double alreadyFoundUtility = getUtilityIfAlreadyFound(key, curdepth);

    if (alreadyFoundUtility != null) {
      return new Double(alreadyFoundUtility).doubleValue();
    }
    // end check

    // Find the utility from scratch and recursion:
    if (curdepth == 0) {
      if (isDarkPlayerCurrentTurn) {
        return utilityFunc.getEstimatedUtilityForDarkPlayer(setup, isDarkPlayerCurrentTurn);
      } else {
        return -utilityFunc.getEstimatedUtilityForDarkPlayer(setup, isDarkPlayerCurrentTurn);
      }
    } else {
      ArrayList<checkersSetup.Turn> turnChoices =
          BasicCheckersAIFunctions.getAllPossiblePlayerOptionsFor1Turn(
              setup, isDarkPlayerCurrentTurn);

      if (turnChoices.size() == 0) {
        // horrible position:
        return -BasicCheckersAIFunctions.DARK_WIN_UTILITY;
      }

      setup.playTurn(turnChoices.get(0));
      // op = OPPONENT!
      double opWorstPosUtil =
          getEstUtilityOfPosition(setup, !isDarkPlayerCurrentTurn, curdepth - 1);
      setup.reverseTurn(turnChoices.get(0));

      double currOpPosUtil;

      for (int i = 1; i < turnChoices.size(); i++) {
        setup.playTurn(turnChoices.get(i));

        currOpPosUtil = getEstUtilityOfPosition(setup, !isDarkPlayerCurrentTurn, curdepth - 1);

        if (currOpPosUtil < opWorstPosUtil) {
          opWorstPosUtil = currOpPosUtil;
        }

        setup.reverseTurn(turnChoices.get(i));
      }
      ret = -opWorstPosUtil;
      // End finding utility from scratch

      // TESTING SLOW
      if (debug) {
        sanityTestKeyBeforeAndAfter(setup, isDarkPlayerCurrentTurn, key);
      }
      // END TESTING

      // ADD analysed position to tree:
      addPositionToListOfAnalysedPositions(key, isDarkPlayerCurrentTurn, curdepth, ret);

      return ret;
    }
  }