コード例 #1
0
ファイル: Blockage.cs プロジェクト: rudzen/ChessLib
        private BitBoard ComputeDynamicFencedPawns(Player them)
        {
            // reverse order of Down
            var down = them.IsBlack
                ? Directions.South
                : Directions.North;

            var result = BitBoard.Empty;

            for (File f = Files.FileA; f < Files.FileNb; ++f)
            {
                var sq = NextFenceRankSquare(f, them);
                var b  = sq.ForwardFile(them) & _theirPawns;
                while (!b.IsEmpty)
                {
                    sq = BitBoards.PopLsb(ref b) + down;
                    if (_pos.GetPiece(sq) == _ourPawn)
                    {
                        result |= sq;
                    }
                }
            }

            return(result);
        }
コード例 #2
0
ファイル: Blockage.cs プロジェクト: rudzen/ChessLib
        /// <summary>
        /// Computes the fence ranks
        /// </summary>
        private void ComputeFenceRanks()
        {
            var covered = _fence;

            while (covered)
            {
                var sq = BitBoards.PopLsb(ref covered);
                var(r, f)             = sq.RankFile;
                _fenceRank[f.AsInt()] = r;
            }
        }
コード例 #3
0
ファイル: BitboardTests.cs プロジェクト: rudzen/ChessLib
        public void BitBoardOrALlTest()
        {
            var baseSquares = new Square[] { Squares.a1, Squares.a2, Squares.a3, Squares.a4, Squares.a5, Squares.a6, Squares.a7, Squares.a8 };
            var bb          = BitBoard.Empty.OrAll(baseSquares);

            while (!bb.IsEmpty)
            {
                var s     = BitBoards.PopLsb(ref bb);
                var valid = Array.BinarySearch(baseSquares, s) > -1;
                Assert.True(valid);
            }
        }
コード例 #4
0
ファイル: Blockage.cs プロジェクト: rudzen/ChessLib
        /// <summary>
        /// Computes whether the current position contains a pawn fence which makes the game a draw.
        /// </summary>
        /// <returns>true if the game is a draw position - otherwise false</returns>
        public bool IsBlocked()
        {
            // Quick check if there is only pawns and kings on the board It might be possible to
            // have a minor piece and exchange it into a passing pawn
            if (_pos.Board.PieceCount(PieceTypes.AllPieces) > _pos.Board.PieceCount(PieceTypes.Pawn) + 2)
            {
                return(false);
            }

            var up = _us.PawnPushDistance();

            MarkOurPawns(up);
            MarkTheirPawns();

            var isFenceFormed = IsFenceFormed();

            if (!isFenceFormed)
            {
                return(false);
            }

            ComputeFenceRanks();

            var ourKsq   = _pos.GetKingSquare(_us);
            var theirKsq = _pos.GetKingSquare(_them);

            if (ourKsq.Rank.RelativeRank(_us) > _fenceRank[ourKsq.File.AsInt()].RelativeRank(_us))
            {
                return(false);
            }

            _dynamicPawns |= ComputeDynamicFencedPawns(_them);

            while (_dynamicPawns)
            {
                var sq = BitBoards.PopLsb(ref _dynamicPawns);
                var(r, f) = sq.RankFile;
                var rr = sq.RelativeRank(_us);

                if (r > _fenceRank[f.AsInt()])
                {
                    if ((_theirPawns & sq.PassedPawnFrontAttackSpan(_us)).IsEmpty && (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr))
                    {
                        return(false);
                    }
                }
                else if (_fence & sq)
                {
                    if (rr >= Ranks.Rank6)
                    {
                        return(false);
                    }

                    if (_pos.GetPiece(sq + _us.PawnDoublePushDistance()) != _theirPawn)
                    {
                        if (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr)
                        {
                            return(false);
                        }

                        if (f != Files.FileA &&
                            _pos.GetPiece(sq + Directions.West) != _ourPawn ||
                            BitBoards.PopCount(_ourPawns & PreviousFile(f)) > 1 ||
                            (_fixedPawn & (sq + Directions.West)).IsEmpty ||
                            (_fence & (sq + Directions.West)).IsEmpty)
                        {
                            return(false);
                        }
                        if (f != Files.FileH &&
                            _pos.GetPiece(sq + Directions.East) != _ourPawn ||
                            BitBoards.PopCount(_ourPawns & NextFile(f)) > 1 ||
                            (_fixedPawn & (sq + Directions.East)).IsEmpty ||
                            (_fence & (sq + Directions.East)).IsEmpty)
                        {
                            return(false);
                        }
                    }

                    if ((sq + _us.PawnDoublePushDistance()).PawnAttack(_us) & _theirPawns)
                    {
                        return(false);
                    }

                    if (BitBoards.PopCount(_ourPawns & f) > 1)
                    {
                        return(false);
                    }
                }
                else if (r < _fenceRank[f.AsInt()])
                {
                    sq += up;
                    r   = sq.Rank;
                    rr  = sq.RelativeRank(_us);
                    while ((_fence & Square.Make(r, f)).IsEmpty)
                    {
                        var pawnAttacks = sq.PawnAttack(_us);
                        if (_theirPawns & pawnAttacks)
                        {
                            return(false);
                        }

                        if (_pos.GetPiece(sq) == _ourPawn)
                        {
                            break;
                        }

                        sq += up;
                        r   = sq.Rank;
                    }

                    if ((_fence & Square.Make(r, f)).IsEmpty || _pos.IsOccupied(sq))
                    {
                        continue;
                    }

                    if (rr >= Ranks.Rank6)
                    {
                        return(false);
                    }

                    if ((_theirPawns & (sq + _us.PawnDoublePushDistance())).IsEmpty)
                    {
                        if (theirKsq.File != f || theirKsq.Rank.RelativeRank(_us) < rr)
                        {
                            return(false);
                        }

                        if (f != Files.FileA &&
                            _pos.GetPiece(sq + Directions.West) != _ourPawn ||
                            BitBoards.PopCount(_ourPawns & (f - 1)) > 1 ||
                            (_fixedPawn & Square.Make(r, PreviousFile(f))).IsEmpty ||
                            (_fence & Square.Make(r, PreviousFile(f))).IsEmpty)
                        {
                            return(false);
                        }
                        if (f != Files.FileH &&
                            _pos.GetPiece(sq + Directions.East) != _ourPawn ||
                            BitBoards.PopCount(_ourPawns & (f + 1)) > 1 ||
                            (_fixedPawn & Square.Make(r, NextFile(f))).IsEmpty ||
                            (_fence & Square.Make(r, NextFile(f))).IsEmpty)
                        {
                            return(false);
                        }
                    }

                    if ((sq + up).PawnAttack(_us) & _theirPawns)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }