// Loading the table from a file public bool Load(string fileName) { // Open the file as a Java tokenizer using (var sr = new StreamReader(fileName)) { // Create a game board on which to "play" the opening sequences stored in // the book, so that we know which position to associate with which move jcBoard board = new jcBoard(); jcMove mov = new jcMove(); jcMoveListGenerator successors = new jcMoveListGenerator(); // How many lines of play do we have in the book? var lines = File.ReadAllLines(fileName); int numLines = lines.Length; for (int wak = 0; wak < numLines; wak++) { // Begin the line of play with a clean board board.StartingBoard(); // Load the continuation var lineNums = lines[wak].Split(' '); for (int i = 0; i < lineNums.Length; i++) { if (lineNums[i] == "END") break; successors.ComputeLegalMoves(board); var source = Convert.ToInt32(lineNums[i]); var destination = Convert.ToInt32(lineNums[i + 1]); i++; mov = successors.FindMoveForSquares(source, destination); StoreMove(board, mov); board.ApplyMove(mov); } } } return true; }
// private jcMove UnrolledAlphabeta // The standard alphabeta, with the top level "unrolled" so that it can // return a jcMove structure instead of a mere minimax value // See jcAISearchAgent.Alphabeta for detailed comments on this code private jcMove UnrolledAlphabeta(jcBoard theBoard, int depth, int alpha, int beta) { jcMove BestMov = new jcMove(); jcMoveListGenerator movegen = new jcMoveListGenerator(); movegen.ComputeLegalMoves(theBoard); HistoryTable.SortMoveList(movegen, theBoard.GetCurrentPlayer()); jcBoard newBoard = new jcBoard(); int bestSoFar; bestSoFar = ALPHABETA_MINVAL; int currentAlpha = alpha; jcMove mov; // Loop on the successors while((mov = movegen.Next()) != null) { // Compute a board position resulting from the current successor newBoard.Clone(theBoard); newBoard.ApplyMove(mov); // And search it in turn int movScore = AlphaBeta(MINNODE, newBoard, depth - 1, currentAlpha, beta); // Ignore illegal moves in the alphabeta evaluation if(movScore == ALPHABETA_ILLEGAL) continue; currentAlpha = Math.Max(currentAlpha, movScore); // Is the current successor better than the previous best? if(movScore > bestSoFar) { BestMov.Copy(mov); bestSoFar = movScore; BestMov.MoveEvaluation = bestSoFar; // Can we cutoff now? if(bestSoFar >= beta) { TransTable.StoreBoard(theBoard, bestSoFar, jcMove.EVALTYPE_UPPERBOUND, depth, MoveCounter); // Add this move's efficiency in the HistoryTable HistoryTable.AddCount(theBoard.GetCurrentPlayer(), mov); return BestMov; } } } // Test for checkmate or stalemate if(bestSoFar <= ALPHABETA_GIVEUP) { newBoard.Clone(theBoard); jcMoveListGenerator secondary = new jcMoveListGenerator(); newBoard.SwitchSides(); if(secondary.ComputeLegalMoves(newBoard)) { // Then, we are not in check and may continue our efforts. HistoryTable.SortMoveList(movegen, newBoard.GetCurrentPlayer()); movegen.ResetIterator(); BestMov.MoveType = jcMove.MOVE_STALEMATE; BestMov.MovingPiece = jcBoard.KING + theBoard.GetCurrentPlayer(); while((mov = movegen.Next()) != null) { newBoard.Clone(theBoard); newBoard.ApplyMove(mov); if(secondary.ComputeLegalMoves(newBoard)) { BestMov.MoveType = jcMove.MOVE_RESIGN; } } } else { // We're in check and our best hope is GIVEUP or worse, so either we are // already checkmated or will be soon, without hope of escape BestMov.MovingPiece = jcBoard.KING + theBoard.GetCurrentPlayer(); BestMov.MoveType = jcMove.MOVE_RESIGN; } } // If we haven't returned yet, we have found an accurate minimax score // for a position which is neither a checkmate nor a stalemate TransTable.StoreBoard(theBoard, bestSoFar, jcMove.EVALTYPE_ACCURATE, depth, MoveCounter); return BestMov; }