// 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; } }