Exemplo n.º 1
0
        public void UndoMove(int move)
        {
            var fromIndex          = MoveUtil.GetFromIndex(move);
            var toIndex            = MoveUtil.GetToIndex(move);
            var toMask             = 1L << toIndex;
            var fromToMask         = (1L << fromIndex) ^ toMask;
            var sourcePieceIndex   = MoveUtil.GetSourcePieceIndex(move);
            var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move);

            PopHistoryValues();

            // undo move
            Pieces[ColorToMoveInverse][All] ^= fromToMask;
            Pieces[ColorToMoveInverse][sourcePieceIndex] ^= fromToMask;
            PieceIndexes[fromIndex] = sourcePieceIndex;
            PsqtScore += EvalConstants.Psqt[sourcePieceIndex][ColorToMoveInverse][fromIndex] -
                         EvalConstants.Psqt[sourcePieceIndex][ColorToMoveInverse][toIndex];

            switch (sourcePieceIndex)
            {
            case Empty:
                // not necessary but provides a table-index
                break;

            case Pawn:
                PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][fromIndex];
                if (MoveUtil.IsPromotion(move))
                {
                    Phase       += EvalConstants.Phase[MoveUtil.GetMoveType(move)];
                    MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][MoveUtil.GetMoveType(move)] -
                                   MaterialUtil.Values[ColorToMoveInverse][Pawn];
                    Pieces[ColorToMoveInverse][Pawn] ^= toMask;
                    Pieces[ColorToMoveInverse][MoveUtil.GetMoveType(move)] ^= toMask;
                    PsqtScore += EvalConstants.Psqt[Pawn][ColorToMoveInverse][toIndex]
                                 - EvalConstants.Psqt[MoveUtil.GetMoveType(move)][ColorToMoveInverse][toIndex];
                }
                else
                {
                    PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex];
                }

                break;

            case King:
                if (MoveUtil.IsCastlingMove(move))
                {
                    CastlingUtil.UncastleRookUpdatePsqt(this, toIndex);
                }

                KingIndex[ColorToMoveInverse] = fromIndex;
                break;
            }

            // undo hit
            switch (attackedPieceIndex)
            {
            case Empty:
                break;

            case Pawn:
                if (MoveUtil.IsEpMove(move))
                {
                    PieceIndexes[toIndex] = Empty;
                    toIndex += ColorFactor8[ColorToMove];
                    toMask   = Util.PowerLookup[toIndex];
                }

                PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][toIndex];
                goto default;

            // fall-through
            default:
                PsqtScore   += EvalConstants.Psqt[attackedPieceIndex][ColorToMove][toIndex];
                Phase       -= EvalConstants.Phase[attackedPieceIndex];
                MaterialKey += MaterialUtil.Values[ColorToMove][attackedPieceIndex];
                Pieces[ColorToMove][All] |= toMask;
                Pieces[ColorToMove][attackedPieceIndex] |= toMask;
                break;
            }

            PieceIndexes[toIndex] = attackedPieceIndex;
            AllPieces             = Pieces[ColorToMove][All] | Pieces[ColorToMoveInverse][All];
            EmptySpaces           = ~AllPieces;
            ChangeSideToMove();
            SetCheckingPinnedAndDiscoPieces();

            if (EngineConstants.Assert)
            {
                ChessBoardTestUtil.TestValues(this);
            }
        }
Exemplo n.º 2
0
        public bool IsValidMove(int move)
        {
            // check piece at from square
            var fromIndex  = MoveUtil.GetFromIndex(move);
            var fromSquare = Util.PowerLookup[fromIndex];

            if ((Pieces[ColorToMove][MoveUtil.GetSourcePieceIndex(move)] & fromSquare) == 0)
            {
                return(false);
            }

            // check piece at to square
            var toIndex            = MoveUtil.GetToIndex(move);
            var toSquare           = Util.PowerLookup[toIndex];
            var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move);

            if (attackedPieceIndex == 0)
            {
                if (PieceIndexes[toIndex] != Empty)
                {
                    return(false);
                }
            }
            else
            {
                if ((Pieces[ColorToMoveInverse][attackedPieceIndex] & toSquare) == 0 && !MoveUtil.IsEpMove(move))
                {
                    return(false);
                }
            }

            // check if move is possible
            switch (MoveUtil.GetSourcePieceIndex(move))
            {
            case Pawn:
                if (MoveUtil.IsEpMove(move))
                {
                    return(toIndex == EpIndex && IsLegalEpMove(fromIndex));
                }
                else
                {
                    if (ColorToMove == White)
                    {
                        if (fromIndex > toIndex)
                        {
                            return(false);
                        }

                        // 2-move
                        if (toIndex - fromIndex == 16 && (AllPieces & Util.PowerLookup[fromIndex + 8]) != 0)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (fromIndex < toIndex)
                        {
                            return(false);
                        }

                        // 2-move
                        if (fromIndex - toIndex == 16 && (AllPieces & Util.PowerLookup[fromIndex - 8]) != 0)
                        {
                            return(false);
                        }
                    }
                }

                break;

            case Knight:
                break;

            case Bishop:
            // fall-through
            case Rook:
            // fall-through
            case Queen:
                if ((InBetween[fromIndex][toIndex] & AllPieces) != 0)
                {
                    return(false);
                }

                break;

            case King:
                if (!MoveUtil.IsCastlingMove(move))
                {
                    return(IsLegalKingMove(move));
                }
                var castlingIndexes = CastlingUtil.GetCastlingIndexes(this);
                while (castlingIndexes != 0)
                {
                    if (toIndex == BitOperations.TrailingZeroCount(castlingIndexes))
                    {
                        return(CastlingUtil.IsValidCastlingMove(this, fromIndex, toIndex));
                    }

                    castlingIndexes &= castlingIndexes - 1;
                }

                return(false);
            }

            if ((fromSquare & PinnedPieces) != 0)
            {
                if ((PinnedMovement[fromIndex][KingIndex[ColorToMove]] & toSquare) == 0)
                {
                    return(false);
                }
            }

            if (CheckingPieces == 0)
            {
                return(true);
            }
            if (attackedPieceIndex == 0)
            {
                return(IsLegalNonKingMove(move));
            }

            if (BitOperations.PopCount((ulong)CheckingPieces) == 2)
            {
                return(false);
            }

            return((toSquare & CheckingPieces) != 0);
        }
Exemplo n.º 3
0
        public void DoMove(int move)
        {
            MoveCount++;

            var fromIndex          = MoveUtil.GetFromIndex(move);
            var toIndex            = MoveUtil.GetToIndex(move);
            var toMask             = 1L << toIndex;
            var fromToMask         = (1L << fromIndex) ^ toMask;
            var sourcePieceIndex   = MoveUtil.GetSourcePieceIndex(move);
            var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move);

            if (EngineConstants.Assert)
            {
                Assert.IsTrue(move != 0);
                Assert.IsTrue(attackedPieceIndex != King);
                Assert.IsTrue(attackedPieceIndex == 0 || (Util.PowerLookup[toIndex] & Pieces[ColorToMove][All]) == 0);
                Assert.IsTrue(IsValidMove(move));
            }

            PushHistoryValues();

            ZobristKey ^= Zobrist.Piece[ColorToMove][sourcePieceIndex][fromIndex] ^
                          Zobrist.Piece[ColorToMove][sourcePieceIndex][toIndex] ^ Zobrist.SideToMove;
            if (EpIndex != 0)
            {
                ZobristKey ^= Zobrist.EpIndex[EpIndex];
                EpIndex     = 0;
            }

            Pieces[ColorToMove][All] ^= fromToMask;
            Pieces[ColorToMove][sourcePieceIndex] ^= fromToMask;
            PieceIndexes[fromIndex] = Empty;
            PieceIndexes[toIndex]   = sourcePieceIndex;
            PsqtScore += EvalConstants.Psqt[sourcePieceIndex][ColorToMove][toIndex] -
                         EvalConstants.Psqt[sourcePieceIndex][ColorToMove][fromIndex];

            switch (sourcePieceIndex)
            {
            case Pawn:
                PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][fromIndex];
                if (MoveUtil.IsPromotion(move))
                {
                    Phase       -= EvalConstants.Phase[MoveUtil.GetMoveType(move)];
                    MaterialKey += MaterialUtil.Values[ColorToMove][MoveUtil.GetMoveType(move)] -
                                   MaterialUtil.Values[ColorToMove][Pawn];
                    Pieces[ColorToMove][Pawn] ^= toMask;
                    Pieces[ColorToMove][MoveUtil.GetMoveType(move)] |= toMask;
                    PieceIndexes[toIndex] = MoveUtil.GetMoveType(move);
                    ZobristKey           ^= Zobrist.Piece[ColorToMove][Pawn][toIndex] ^
                                            Zobrist.Piece[ColorToMove][MoveUtil.GetMoveType(move)][toIndex];
                    PsqtScore += EvalConstants.Psqt[MoveUtil.GetMoveType(move)][ColorToMove][toIndex] -
                                 EvalConstants.Psqt[Pawn][ColorToMove][toIndex];
                }
                else
                {
                    PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][toIndex];
                    // 2-move
                    if (InBetween[fromIndex][toIndex] != 0)
                    {
                        if ((StaticMoves.PawnAttacks[ColorToMove][
                                 BitOperations.TrailingZeroCount(InBetween[fromIndex][toIndex])]
                             & Pieces[ColorToMoveInverse][Pawn]) != 0)
                        {
                            EpIndex     = BitOperations.TrailingZeroCount(InBetween[fromIndex][toIndex]);
                            ZobristKey ^= Zobrist.EpIndex[EpIndex];
                        }
                    }
                }

                break;

            case Rook:
                if (CastlingRights != 0)
                {
                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                    CastlingRights = CastlingUtil.GetRookMovedOrAttackedCastlingRights(CastlingRights, fromIndex);
                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                }

                break;

            case King:
                KingIndex[ColorToMove] = toIndex;
                if (CastlingRights != 0)
                {
                    if (MoveUtil.IsCastlingMove(move))
                    {
                        CastlingUtil.CastleRookUpdateKeyAndPsqt(this, toIndex);
                    }

                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                    CastlingRights = CastlingUtil.GetKingMovedCastlingRights(CastlingRights, fromIndex);
                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                }

                break;
            }

            // piece hit?
            switch (attackedPieceIndex)
            {
            case Empty:
                break;

            case Pawn:
                if (MoveUtil.IsEpMove(move))
                {
                    toIndex += ColorFactor8[ColorToMoveInverse];
                    toMask   = Util.PowerLookup[toIndex];
                    PieceIndexes[toIndex] = Empty;
                }

                PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex];
                PsqtScore      -= EvalConstants.Psqt[Pawn][ColorToMoveInverse][toIndex];
                Pieces[ColorToMoveInverse][All]  ^= toMask;
                Pieces[ColorToMoveInverse][Pawn] ^= toMask;
                ZobristKey  ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex];
                MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][Pawn];
                break;

            case Rook:
                if (CastlingRights != 0)
                {
                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                    CastlingRights = CastlingUtil.GetRookMovedOrAttackedCastlingRights(CastlingRights, toIndex);
                    ZobristKey    ^= Zobrist.Castling[CastlingRights];
                }

                goto default;

            // fall-through
            default:
                Phase     += EvalConstants.Phase[attackedPieceIndex];
                PsqtScore -= EvalConstants.Psqt[attackedPieceIndex][ColorToMoveInverse][toIndex];
                Pieces[ColorToMoveInverse][All] ^= toMask;
                Pieces[ColorToMoveInverse][attackedPieceIndex] ^= toMask;
                ZobristKey  ^= Zobrist.Piece[ColorToMoveInverse][attackedPieceIndex][toIndex];
                MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][attackedPieceIndex];
                break;
            }

            AllPieces   = Pieces[ColorToMove][All] | Pieces[ColorToMoveInverse][All];
            EmptySpaces = ~AllPieces;
            ChangeSideToMove();
            SetCheckingPinnedAndDiscoPieces();

            if (EngineConstants.Assert)
            {
                ChessBoardTestUtil.TestValues(this);
            }
        }