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)); }
public Option <Move.Move> FindBestMove(Position.Position currentPosition) { evaluator.OnNewSearch(currentPosition); Option <Move.Move> bestMove = Option.None <Move.Move>(); int bestMoveEvaluation = MinEvaluationValue; foreach (var move in MoveGenerator.GenerateLegalMoves(currentPosition)) { currentPosition.PlayMove(move); var evaluation = -CalculateEvaluationRecursively( currentPosition, currentDepth: 1) .ValueOr(-MinEvaluationValue); if (!bestMove.HasValue || evaluation >= bestMoveEvaluation) { bestMove = Option.Some(move); bestMoveEvaluation = evaluation; } currentPosition.UndoMove(); } return(bestMove); }