private Option <int> CalculateEvaluationRecursively( Position.Position position, int currentDepth) { var bestMove = Move.Move.NullMove; var bestMoveEvaluation = MinEvaluationValue; bool hasLegalMove = false; var playerEvaluationMultiplier = GetPlayerEvaluationMultiplier(position.PlayerToMove); var playerToMove = position.PlayerToMove; var pseudoLegalMoves = MoveGenerator.GeneratePseudoLegalMoves(position); foreach (var move in pseudoLegalMoves) { position.PlayMove(move); if (!IsPlayedMoveLegal(position)) { position.UndoMove(); continue; } hasLegalMove = true; int movePriority = CalculateMovePriority(move, currentDepth); if (movePriority < MinPriorityToConsiderMove) { position.UndoMove(); continue; } evaluator.OnMovePlayed(move, playerToMove); var evaluation = -CalculateEvaluationRecursively( position, currentDepth + 1) .ValueOr(() => - playerEvaluationMultiplier * evaluator.GetCurrentEvaluation()); if (evaluation >= bestMoveEvaluation) { bestMove = move; bestMoveEvaluation = evaluation; } position.UndoMove(); evaluator.OnUndoMove(); } if (!hasLegalMove) { return(Option.Some( GetEvaluationForPositionWithoutLegalMoves( position, playerEvaluationMultiplier))); } return(bestMove.IsNullMove ? Option.None <int>() : Option.Some(bestMoveEvaluation)); }