Example #1
0
        private string ValidateBasic()
        {
            var error = string.Empty;

            if (_pos.SideToMove != Player.White && _pos.SideToMove != Player.Black)
            {
                error = AddError(error, $"{nameof(_pos.SideToMove)} is not a valid");
            }

            if (_board.PieceAt(_pos.GetKingSquare(Player.White)) != Pieces.WhiteKing)
            {
                error = AddError(error, "white king position is not a white king");
            }

            if (_board.PieceAt(_pos.GetKingSquare(Player.Black)) != Pieces.BlackKing)
            {
                error = AddError(error, "black king position is not a black king");
            }

            if (_pos.EnPassantSquare != Square.None && _pos.EnPassantSquare.RelativeRank(_pos.SideToMove) != Ranks.Rank6)
            {
                error = AddError(error, $"{nameof(_pos.EnPassantSquare)} square is not on rank 6");
            }

            return(error);
        }
Example #2
0
        /// <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);
        }