Пример #1
0
        public bool IsRepetition(int move)
        {
            if (!EngineConstants.EnableRepetitionTable)
            {
                return(false);
            }

            // if move was an attacking-move or pawn move, no repetition
            if (!MoveUtil.IsQuiet(move) || MoveUtil.GetSourcePieceIndex(move) == Pawn)
            {
                return(false);
            }

            var moveCountMin = Math.Max(0, MoveCounter - 50);

            for (var i = MoveCounter - 2; i >= moveCountMin; i -= 2)
            {
                if (ZobristKey != ZobristKeyHistory[i])
                {
                    continue;
                }
                if (Statistics.Enabled)
                {
                    Statistics.Repetitions++;
                }

                return(true);
            }

            return(false);
        }
Пример #2
0
        public static int GetSeeCaptureScore(ChessBoard cb, int move)
        {
            if (EngineConstants.Assert)
            {
                if (MoveUtil.GetAttackedPieceIndex(move) == 0)
                {
                    Assert.IsTrue(MoveUtil.GetMoveType(move) != 0);
                }
            }

            var index       = MoveUtil.GetToIndex(move);
            var allPieces   = cb.AllPieces & ~Util.PowerLookup[MoveUtil.GetFromIndex(move)];
            var slidingMask = MagicUtil.GetQueenMovesEmptyBoard(index) & allPieces;

            // add score when promotion
            if (MoveUtil.IsPromotion(move))
            {
                return(EvalConstants.PromotionScore[MoveUtil.GetMoveType(move)] +
                       EvalConstants.Material[MoveUtil.GetAttackedPieceIndex(move)]
                       - GetSeeScore(cb, cb.ColorToMoveInverse, index, MoveUtil.GetMoveType(move), allPieces,
                                     slidingMask));
            }

            return(EvalConstants.Material[MoveUtil.GetAttackedPieceIndex(move)]
                   - GetSeeScore(cb, cb.ColorToMoveInverse, index, MoveUtil.GetSourcePieceIndex(move), allPieces,
                                 slidingMask));
        }
Пример #3
0
 public void AddCounterMove(int color, int parentMove, int counterMove)
 {
     if (EngineConstants.EnableCounterMoves)
     {
         _counterMoves[color][MoveUtil.GetSourcePieceIndex(parentMove)][MoveUtil.GetToIndex(parentMove)] =
             counterMove;
     }
 }
Пример #4
0
 public void SetMvvlvaScores()
 {
     for (var j = _nextToMove[_ply]; j < _nextToGenerate[_ply]; j++)
     {
         _moveScores[j] = MoveUtil.GetAttackedPieceIndex(_moves[j]) * 6 -
                          MoveUtil.GetSourcePieceIndex(_moves[j]);
         if (MoveUtil.GetMoveType(_moves[j]) == MoveUtil.TypePromotionQ)
         {
             _moveScores[j] += Queen * 6;
         }
     }
 }
Пример #5
0
        private static bool MoveEquals(string moveString, MoveWrapper bestMove)
        {
            var move        = bestMove.Move;
            var sourceIndex = MoveUtil.GetSourcePieceIndex(move);

            return(moveString.Length switch
            {
                2 => sourceIndex == ChessConstants.Pawn && moveString.Substring(0, 1).Equals(bestMove.ToFile + "") &&
                moveString.Substring(1, 1).Equals(bestMove.ToRank + ""),
                3 when moveString.Substring(0, 1).ToLower().Equals(moveString.Substring(0, 1)) =>
                sourceIndex == ChessConstants.Pawn && moveString.Substring(0, 1).Equals(bestMove.FromFile + "") &&
                moveString.Substring(1, 1).Equals(bestMove.ToFile + "") &&
                moveString.Substring(2, 1).Equals(bestMove.ToRank + ""),
                3 => moveString.Substring(0, 1).Equals(ChessConstants.FenWhitePieces[sourceIndex]) &&
                moveString.Substring(1, 1).Equals(bestMove.ToFile + "") &&
                moveString.Substring(2, 1).Equals(bestMove.ToRank + ""),
                4 => moveString.Substring(0, 1).Equals(ChessConstants.FenWhitePieces[sourceIndex]) &&
                moveString.Substring(1, 1).Equals(bestMove.FromFile + "") &&
                moveString.Substring(2, 1).Equals(bestMove.ToFile + "") &&
                moveString.Substring(3, 1).Equals(bestMove.ToRank + ""),
                _ => throw new ArgumentException("Unknown move string: " + moveString)
            });
Пример #6
0
 public int GetCounter(int color, int parentMove)
 {
     return(_counterMoves[color][MoveUtil.GetSourcePieceIndex(parentMove)][MoveUtil.GetToIndex(parentMove)]);
 }
Пример #7
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);
        }
Пример #8
0
 public bool IsLegal(int move)
 {
     return(MoveUtil.GetSourcePieceIndex(move) != King || IsLegalKingMove(move));
 }
Пример #9
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);
            }
        }
Пример #10
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);
            }
        }