int Search(FastBoardNode node, int searchDepth, int plyFromRoot, int alpha, int beta, int color) { if (searchDepth == 0) { using (diagnostics.quiescence.Measure()) return(QuiescenceSearch(node, plyFromRoot, alpha, beta, color)); } List <FastMove> moves; using (diagnostics.moveGen.Measure()) { moves = moveCache[searchDepth]; moves.Clear(); node.AddAllPossibleMoves(moves, node.currentMove); } evaluationData.Prepare(node); using (diagnostics.moveSort.Measure()) { OrderMoves(node, moves, plyFromRoot); } bool isTerminal = true; int value = int.MinValue; foreach (var move in moves) { if (cancellationRequested) { return(0); } using (diagnostics.apply.Measure()) node.DoMove(move); bool isKingVulnerable; using (diagnostics.moveValidate.Measure()) isKingVulnerable = node.IsChecking(node.currentMove); if (isKingVulnerable) { diagnostics.invalidMoves++; using (diagnostics.apply.Measure()) node.UndoMove(move); continue; } isTerminal = false; int currentValue = -Search(node, searchDepth - 1, plyFromRoot + 1, -beta, -alpha, -color); if (previousOrderingEnabled && plyFromRoot == 0) { previousScores[move] = currentValue; } using (diagnostics.apply.Measure()) node.UndoMove(move); if (currentValue > value) { if (plyFromRoot == 0) { bestMoveThisIteration = move; } value = currentValue; } alpha = Math.Max(alpha, value); if (alpha >= beta) { diagnostics.searchCutoff++; break; } } if (isTerminal) { value = color * EvaluateTerminalBoard(node, plyFromRoot); } return(value); }
int QuiescenceSearch(FastBoardNode node, int plyFromRoot, int alpha, int beta, int color) { int eval; evaluationData.Prepare(node); using (diagnostics.quiescenceEval.Measure()) eval = color * EvaluateBoard(node, plyFromRoot); if (!quiescenceSearchEnabled) { return(eval); } if (eval >= beta) { diagnostics.quiescenceCutoff++; return(beta); } if (eval > alpha) { alpha = eval; } List <FastMove> moves; using (diagnostics.quiescenceMoveGen.Measure()) { moves = new List <FastMove>(10); node.AddAllPossibleMoves(moves, node.currentMove, generateQuiet: false); } using (diagnostics.quiescenceMoveSort.Measure()) OrderMoves(node, moves, -1); bool maybeTerminal = true; int value = int.MinValue; foreach (var move in moves) { if (cancellationRequested) { return(0); } using (diagnostics.quiescenceApply.Measure()) node.DoMove(move); bool isKingVulnerable; using (diagnostics.quiescenceMoveValidate.Measure()) isKingVulnerable = node.IsChecking(node.currentMove); if (isKingVulnerable) { diagnostics.invalidMoves++; using (diagnostics.quiescenceApply.Measure()) node.UndoMove(move); continue; } maybeTerminal = false; int currentValue = -QuiescenceSearch(node, plyFromRoot + 1, -beta, -alpha, -color); using (diagnostics.quiescenceApply.Measure()) node.UndoMove(move); if (currentValue > value) { value = currentValue; } alpha = Math.Max(alpha, value); if (alpha >= beta) { diagnostics.quiescenceCutoff++; break; } } // No non-quiet moves were found from this position if (maybeTerminal) { return(eval); } return(value); }