Пример #1
0
        // Load custom position from fen string
        public void LoadPosition(string fen)
        {
            Initialize();
            var loadedPosition = FenUtility.PositionFromFen(fen);

            // Load pieces into board array and piece lists
            for (int squareIndex = 0; squareIndex < 64; squareIndex++)
            {
                int piece = loadedPosition.squares[squareIndex];
                Square[squareIndex] = piece;

                if (piece != Piece.None)
                {
                    int pieceType        = Piece.PieceType(piece);
                    int pieceColourIndex = (Piece.IsColour(piece, Piece.White)) ? WhiteIndex : BlackIndex;
                    if (Piece.IsSlidingPiece(piece))
                    {
                        if (pieceType == Piece.Queen)
                        {
                            queens[pieceColourIndex].AddPieceAtSquare(squareIndex);
                        }
                        else if (pieceType == Piece.Rook)
                        {
                            rooks[pieceColourIndex].AddPieceAtSquare(squareIndex);
                        }
                        else if (pieceType == Piece.Bishop)
                        {
                            bishops[pieceColourIndex].AddPieceAtSquare(squareIndex);
                        }
                    }
                    else if (pieceType == Piece.Knight)
                    {
                        knights[pieceColourIndex].AddPieceAtSquare(squareIndex);
                    }
                    else if (pieceType == Piece.Pawn)
                    {
                        pawns[pieceColourIndex].AddPieceAtSquare(squareIndex);
                    }
                    else if (pieceType == Piece.King)
                    {
                        KingSquare[pieceColourIndex] = squareIndex;
                    }
                }
            }

            // Side to move
            WhiteToMove       = loadedPosition.whiteToMove;
            ColourToMove      = (WhiteToMove) ? Piece.White : Piece.Black;
            OpponentColour    = (WhiteToMove) ? Piece.Black : Piece.White;
            ColourToMoveIndex = (WhiteToMove) ? 0 : 1;

            // Create gamestate
            int    whiteCastle      = ((loadedPosition.whiteCastleKingside) ? 1 << 0 : 0) | ((loadedPosition.whiteCastleQueenside) ? 1 << 1 : 0);
            int    blackCastle      = ((loadedPosition.blackCastleKingside) ? 1 << 2 : 0) | ((loadedPosition.blackCastleQueenside) ? 1 << 3 : 0);
            int    epState          = loadedPosition.epFile << 4;
            ushort initialGameState = (ushort)(whiteCastle | blackCastle | epState);

            gameStateHistory.Push(initialGameState);
            currentGameState = initialGameState;
            plyCount         = loadedPosition.plyCount;

            // Initialize zobrist key
            ZobristKey = Zobrist.CalculateZobristKey(this);
        }
Пример #2
0
        public void StartSearch()
        {
            InitDebugInfo();

            // Initialize search settings
            bestEvalThisIteration = bestEval = 0;
            bestMoveThisIteration = bestMove = Move.InvalidMove;
            tt.enabled            = settings.useTranspositionTable;

            // Clearing the transposition table before each search seems to help
            // This makes no sense to me, I presume there is a bug somewhere but haven't been able to track it down yet
            if (settings.clearTTEachMove)
            {
                tt.Clear();
            }

            moveGenerator.promotionsToGenerate = settings.promotionsToSearch;
            currentIterativeSearchDepth        = 0;
            abortSearch       = false;
            searchDiagnostics = new SearchDiagnostics();

            // Iterative deepening. This means doing a full search with a depth of 1, then with a depth of 2, and so on.
            // This allows the search to be aborted at any time, while still yielding a useful result from the last search.
            if (settings.useIterativeDeepening)
            {
                var targetDepth = settings.useFixedDepthSearch ? settings.depth : int.MaxValue;

                for (var searchDepth = 1; searchDepth <= targetDepth; searchDepth++)
                {
                    SearchMoves(searchDepth, 0, negativeInfinity, positiveInfinity);
                    if (abortSearch)
                    {
                        break;
                    }

                    currentIterativeSearchDepth = searchDepth;
                    bestMove = bestMoveThisIteration;
                    bestEval = bestEvalThisIteration;

                    // Update diagnostics
                    searchDiagnostics.lastCompletedDepth = searchDepth;
                    searchDiagnostics.move    = bestMove.Name;
                    searchDiagnostics.eval    = bestEval;
                    searchDiagnostics.moveVal = PGNCreator.NotationFromMove(FenUtility.CurrentFen(board), bestMove);

                    // Exit search if found a mate
                    if (IsMateScore(bestEval) && !settings.endlessSearchMode)
                    {
                        break;
                    }
                }
            }
            else
            {
                SearchMoves(settings.depth, 0, negativeInfinity, positiveInfinity);
                bestMove = bestMoveThisIteration;
                bestEval = bestEvalThisIteration;
            }

            onSearchComplete?.Invoke(bestMove);

            if (!settings.useThreading)
            {
                LogDebugInfo();
            }
        }