Example #1
0
 private void CountPieces()
 {
     for (ColorE color = ColorE.White; color <= ColorE.Black; ++color)
     {
         Bitboard occupy = Occupies[(byte)color];
         for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type)
         {
             Bitboard piece = Pieces[(byte)type];
             PieceCount[(byte)color, (byte)type] = BitBoard.CountSets(occupy & piece);
         }
     }
 }
Example #2
0
        /// Split Method
        internal static Board ToBoard(string fenString)
        {
            const Board emptyBoard = default(Board);

            if (string.IsNullOrEmpty(fenString))
            {
                return(emptyBoard);
            }

            string[] records   = fenString.Split(new char[] { recordSep }, StringSplitOptions.RemoveEmptyEntries);
            int      numRecord = records.Length;
            // --- full fenString check
            //if( numRecord != 6 ) return emptyBoard;

            Board board = new Board();

            #region Piece placement

            string[] ranks = records[0].Split(rankSep);

            if (ranks.Length != Rank.Ranks)
            {
                return(emptyBoard);
            }

            byte baseSqr = (byte)SquareE.A8;
            foreach (string rank in ranks)
            {
                byte offsetFile = 0;
                foreach (char achar in rank)
                {
                    if (achar >= '1' && achar <= '8')
                    {
                        offsetFile += (byte)(achar - '0');
                    }
                    else
                    {
                        Piece piece = Piece.Parse(achar);

                        if (piece != default(Piece))
                        {// there is a piece
                            ColorE color = piece.Color;
                            PieceE type  = piece.Type;

                            if (color != ColorE.NoColor && type != PieceE.NoPiece)
                            {
                                if (offsetFile >= File.Files)
                                {
                                    return(emptyBoard);
                                }

                                SquareE sqr = (SquareE)(baseSqr + offsetFile);

                                switch (type)
                                {
                                case PieceE.Pawn:
                                    RankE pawnRank = Square._Rank(sqr);
                                    if (pawnRank == RankE.Rank_1 || pawnRank == RankE.Rank_8)
                                    {
                                        return(emptyBoard);
                                    }
                                    if (board.PieceCount[(byte)color, (byte)type] >= 8)
                                    {
                                        return(emptyBoard);
                                    }
                                    break;

                                case PieceE.King:
                                    if (board.PieceCount[(byte)color, (byte)type] >= 1)
                                    {
                                        return(emptyBoard);
                                    }
                                    break;

                                case PieceE.Knight:
                                case PieceE.Bishop:
                                case PieceE.Rook:
                                case PieceE.Queen:
                                    if (board.PieceCount[(byte)color, (byte)PieceE.Pawn] +
                                        board.PieceCount[(byte)color, (byte)PieceE.Knight] +
                                        board.PieceCount[(byte)color, (byte)PieceE.Bishop] +
                                        board.PieceCount[(byte)color, (byte)PieceE.Rook] +
                                        board.PieceCount[(byte)color, (byte)PieceE.Queen]
                                        >= 15)
                                    {
                                        return(emptyBoard);
                                    }
                                    break;
                                }

                                board.PutPiece(piece, sqr);   // put the piece on board
                            }
                        }
                        else
                        {
                            return(emptyBoard);
                        }

                        ++offsetFile;
                    }
                }

                if (offsetFile == 0)  // Allow null lines = /8/
                {
                    offsetFile = File.Files;
                }

                if (offsetFile != File.Files)
                {
                    return(emptyBoard);
                }

                baseSqr -= File.Files;
            }

            for (ColorE color = ColorE.White; color <= ColorE.Black; ++color)
            {
                Bitboard occupy = board.Occupies[(byte)color];
                // check too many total pieces
                if (BitBoard.CountSets(occupy) > 16)
                {
                    return(emptyBoard);
                }

                // check if the number of Pawns plus the number of extra Queens, Rooks, Bishops, Knights
                // (which can result only by promotion) exceeds 8

                // check too many color pieces
                if (board.PieceCount[(byte)color, (byte)PieceE.Pawn] +
                    Math.Max(board.PieceCount[(byte)color, (byte)PieceE.Knight] - 2, 0) +
                    Math.Max(board.PieceCount[(byte)color, (byte)PieceE.Bishop] - 2, 0) +
                    Math.Max(board.PieceCount[(byte)color, (byte)PieceE.Rook] - 2, 0) +
                    Math.Max(board.PieceCount[(byte)color, (byte)PieceE.Queen] - 1, 0)
                    > 8)
                {
                    return(emptyBoard);
                }

                if (board.PieceCount[(byte)color, (byte)PieceE.Bishop] > 1)
                {
                    Bitboard bishops = occupy & board.Pieces[(byte)PieceE.Bishop];

                    byte[] bishopCount = new byte[Color.Colors];

                    //SquareE[] square = BitBoard.GetSquares(occupy & board.Pieces[ (byte) PieceE.Bishop ]);
                    //foreach( SquareE sqr in square )
                    //    ++bishopCount[ (byte) Square._Color(sqr) ];

                    bishopCount[(byte)ColorE.White] = BitBoard.CountSets(BitBoard.LightSquares & bishops);
                    bishopCount[(byte)ColorE.Black] = BitBoard.CountSets(BitBoard.DarkSquares & bishops);

                    if (board.PieceCount[(byte)color, (byte)PieceE.Pawn] +
                        Math.Max(bishopCount[(byte)ColorE.White] - 1, 0) +
                        Math.Max(bishopCount[(byte)ColorE.Black] - 1, 0)
                        > 8)
                    {
                        return(emptyBoard);
                    }
                }

                // check for King
                byte king = board.PieceCount[(byte)color, (byte)PieceE.King];
                if (king != 1)  //Illegal King
                {
                    return(emptyBoard);
                }
            }
            #endregion

            if (numRecord > 1)
            {
                #region Active color

                string aColor = records[1];
                if (string.IsNullOrEmpty(aColor) || aColor.Length != 1)
                {
                    return(emptyBoard);
                }

                char activeColor = char.ToLower(aColor[0]);
                if (activeColor == 'w')
                {
                    board.OnMove = ColorE.White;
                }
                else if (activeColor == 'b')
                {
                    board.OnMove = ColorE.Black;
                }
                else
                {
                    board.OnMove = ColorE.NoColor;
                    return(emptyBoard);
                }
                #endregion
            }

            if (numRecord > 2)
            {
                #region Castling privileges

                string castles = records[2];
                if (string.IsNullOrEmpty(castles))
                {
                    return(emptyBoard);
                }

                if (castles == "-")
                {
                    board.Castle[(byte)ColorE.White].AnyCastle = false;
                    board.Castle[(byte)ColorE.Black].AnyCastle = false;
                }
                else
                {
                    int length = castles.Length;
                    if (length > 4)
                    {
                        return(emptyBoard);
                    }

                    for (byte i = 0; i < length - 1; ++i)
                    {
                        for (byte j = (byte)(i + 1); j < length; ++j)
                        {
                            if (castles[i] == castles[j])
                            {
                                return(emptyBoard);
                            }
                        }
                    }

                    foreach (char castle in castles)
                    {
                        switch (castle)
                        {
                        case 'K':
                        {
                            Bitboard occupy = board.Occupies[(byte)ColorE.White];
                            if (BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.King], SquareE.E1) &&
                                BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.Rook], SquareE.H1))
                            {
                                board.Castle[(byte)ColorE.White].ShortCastle = true;
                            }
                            else
                            {
                                return(emptyBoard);
                            }
                        } break;

                        case 'Q':
                        {
                            Bitboard occupy = board.Occupies[(byte)ColorE.White];
                            if (BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.King], SquareE.E1) &&
                                BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.Rook], SquareE.A1))
                            {
                                board.Castle[(byte)ColorE.White].LongCastle = true;
                            }
                            else
                            {
                                return(emptyBoard);
                            }
                        } break;

                        case 'k':
                        {
                            Bitboard occupy = board.Occupies[(byte)ColorE.Black];
                            if (BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.King], SquareE.E8) &&
                                BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.Rook], SquareE.H8))
                            {
                                board.Castle[(byte)ColorE.Black].ShortCastle = true;
                            }
                            else
                            {
                                return(emptyBoard);
                            }
                        } break;

                        case 'q':
                        {
                            Bitboard occupy = board.Occupies[(byte)ColorE.Black];
                            if (BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.King], SquareE.E8) &&
                                BitBoard.GetSquare(occupy & board.Pieces[(byte)PieceE.Rook], SquareE.A8))
                            {
                                board.Castle[(byte)ColorE.Black].LongCastle = true;
                            }
                            else
                            {
                                return(emptyBoard);
                            }
                        } break;

                        default:
                            return(emptyBoard);
                        }
                    }
                }
                #endregion
            }

            if (numRecord > 3)
            {
                #region EnPassant Target square

                string epSqr = records[3];
                if (string.IsNullOrEmpty(epSqr))
                {
                    return(emptyBoard);
                }

                if (epSqr == "-")
                {
                    board.EnPassant = SquareE.NoSquare;
                }
                else
                {
                    if (epSqr.Length != 2)
                    {
                        return(emptyBoard);
                    }

                    char epFile = char.ToLower(epSqr[0]);
                    if (!(epFile >= 'a' && epFile <= 'h'))
                    {
                        return(emptyBoard);
                    }

                    char epRank = epSqr[1];
                    if (!(epRank == '3' || epRank == '6'))
                    {
                        return(emptyBoard);
                    }

                    if (epRank == '3' &&
                        (
                            board.OnMove != ColorE.Black ||
                            !BitBoard.GetSquare(board.Occupies[(byte)ColorE.White] & board.Pieces[(byte)PieceE.Pawn], Square._Square(epFile, (char)(epRank + 1)))
                        )
                        ||
                        epRank == '6' &&
                        (
                            board.OnMove != ColorE.White ||
                            !BitBoard.GetSquare(board.Occupies[(byte)ColorE.Black] & board.Pieces[(byte)PieceE.Pawn], Square._Square(epFile, (char)(epRank - 1)))
                        )
                        )
                    {
                        return(emptyBoard);
                    }

                    board.EnPassant = Square._Square(epFile, epRank);
                }
                #endregion
            }

            if (numRecord > 4)
            {
                #region HalfMove Clock (Ply)

                byte halfMoveClock;
                if (!byte.TryParse(records[4], out halfMoveClock))
                {
                    return(emptyBoard);
                }

                if (halfMoveClock > 100)
                {
                    return(emptyBoard);
                }

                board.HalfMoveClock = halfMoveClock;
                #endregion
            }

            if (numRecord > 5)
            {
                #region FullMove Counter

                ushort fullMoveCount;
                if (!ushort.TryParse(records[5], out fullMoveCount))
                {
                    return(emptyBoard);
                }

                if (fullMoveCount == 0)
                {
                    fullMoveCount = 1;
                }
                board.FullMoveCount = fullMoveCount;
                #endregion
            }

            return(board);
        }
Example #3
0
        private bool IsLegal()
        {
            ColorE   color;
            Bitboard occupy;

            #region Pieces Count

            for (color = ColorE.White; color <= ColorE.Black; ++color)
            {
                occupy = Occupies[(byte)color];
                // check too many total pieces
                if (BitBoard.CountSets(occupy) > 16)
                {
                    return(false);
                }

                // check if the number of Pawns plus the number of extra Queens, Rooks, Bishops, Knights
                // (which can result only by promotion) exceeds 8

                // check too many color pieces
                if (PieceCount[(byte)color, (byte)PieceE.Pawn]
                    + Math.Max(PieceCount[(byte)color, (byte)PieceE.Queen] - 1, 0)
                    + Math.Max(PieceCount[(byte)color, (byte)PieceE.Rook] - 2, 0)
                    + Math.Max(PieceCount[(byte)color, (byte)PieceE.Bishop] - 2, 0)
                    + Math.Max(PieceCount[(byte)color, (byte)PieceE.Knight] - 2, 0)
                    > 8
                    )
                {
                    return(false);
                }

                if (PieceCount[(byte)color, (byte)PieceE.Bishop] > 1)
                {
                    Bitboard bishops = occupy & Pieces[(byte)PieceE.Bishop];

                    byte[] bishopCount = new byte[Color.Colors];

                    //SquareE[] square = BitBoard.GetSquares(occupy & board.Pieces[ (byte) PieceE.Bishop ]);
                    //foreach( SquareE sqr in square )
                    //    ++bishopCount[ (byte) Square._Color(sqr) ];

                    bishopCount[(byte)ColorE.White] = BitBoard.CountSets(BitBoard.LightSquares & bishops);
                    bishopCount[(byte)ColorE.Black] = BitBoard.CountSets(BitBoard.DarkSquares & bishops);

                    if (PieceCount[(byte)color, (byte)PieceE.Pawn]
                        + Math.Max(bishopCount[(byte)ColorE.White] - 1, 0)
                        + Math.Max(bishopCount[(byte)ColorE.Black] - 1, 0)
                        > 8)
                    {
                        Debug.Assert(false, "Illegal FEN format", "Too many Promotion Bishop of same color of " + color);
                        return(false);
                    }
                }

                // check for King
                byte king = PieceCount[(byte)color, (byte)PieceE.King];
                if (king != 1)  //Illegal King
                {
                    return(false);
                }
            }
            //

            if ((Pieces[(byte)PieceE.Pawn] & (BitBoard.Rank_1 | BitBoard.Rank_8)) != 0)
            {//Pawn rank one or eight
                return(false);
            }
            #endregion

            #region Overlapping

            Bitboard occupied = Occupied;
            if ((Occupies[(byte)ColorE.White] ^
                 Occupies[(byte)ColorE.Black]) !=
                occupied)
            {
                return(false);
            }

            if ((Pieces[(byte)PieceE.Pawn] ^
                 Pieces[(byte)PieceE.Knight] ^
                 Pieces[(byte)PieceE.Bishop] ^
                 Pieces[(byte)PieceE.Rook] ^
                 Pieces[(byte)PieceE.Queen] ^
                 Pieces[(byte)PieceE.King]) !=
                occupied)
            {
                return(false);
            }
            #endregion

            #region Castling

            color  = ColorE.White;
            occupy = Occupies[(byte)color];
            // check the white King is in place for castle
            if (Castle[(byte)color].AnyCastle)
            {
                if (BitBoard.GetSquare(occupy & Pieces[(byte)PieceE.King], SquareE.E1))
                {
                    Bitboard rooks = occupy & Pieces[(byte)PieceE.Rook];
                    // check the white Rook is in place for castle
                    if (Castle[(byte)color].ShortCastle &&
                        !BitBoard.GetSquare(rooks, SquareE.H1))
                    {
                        //Illegal WhiteShortCastle
                        return(false);
                    }
                    if (Castle[(byte)color].LongCastle &&
                        !BitBoard.GetSquare(rooks, SquareE.A1))
                    {
                        //Illegal WhiteLongCastle
                        return(false);
                    }
                }
                else    //Illegal WhiteCastle
                {
                    return(false);
                }
            }

            color  = ColorE.Black;
            occupy = Occupies[(byte)color];
            // check the black King is in place for castle
            if (Castle[(byte)color].AnyCastle)
            {
                if (BitBoard.GetSquare(occupy & Pieces[(byte)PieceE.King], SquareE.E8))
                {
                    Bitboard rooks = occupy & Pieces[(byte)PieceE.Rook];
                    // check the black Rook is in place for castle
                    if (Castle[(byte)color].ShortCastle &&
                        !BitBoard.GetSquare(rooks, SquareE.H8))
                    {
                        //Illegal BlackShortCastle
                        return(false);
                    }
                    if (Castle[(byte)color].LongCastle &&
                        !BitBoard.GetSquare(rooks, SquareE.A8))
                    {
                        //Illegal BlackLongCastle
                        return(false);
                    }
                }
                else    //Illegal BlackCastle
                {
                    return(false);
                }
            }
            #endregion

            #region EnPassant

            if (EnPassant != SquareE.NoSquare)
            {
                if (!Square.IsValid(EnPassant))
                {
                    return(false);
                }

                if (OnMove == ColorE.White &&
                    (Square._Rank(EnPassant) != RankE.Rank_6 || !BitBoard.GetSquare(Occupies[(byte)ColorE.Black] & Pieces[(byte)PieceE.Pawn], (SquareE)(EnPassant - 8)))
                    ||
                    OnMove == ColorE.Black &&
                    (Square._Rank(EnPassant) != RankE.Rank_3 || !BitBoard.GetSquare(Occupies[(byte)ColorE.White] & Pieces[(byte)PieceE.Pawn], (SquareE)(EnPassant + 8))))
                {
                    return(false);
                }
            }
            #endregion

            #region Move

            if ( //0 < HalfMove ||
                HalfMoveClock > 100)
            {
                return(false);
            }
            //if( MoveCount < 0 ) return false;
            #endregion

            #region KingCheck And Move

            /*
             * // check if the side which is not to move is in check
             * if(
             *  (board.Status.WhiteTurn && board.IsBlackKingInCheck)
             || (board.Status.BlackTurn && board.IsWhiteKingInCheck)
             ||)
             ||{
             || throw new ArgumentException(Resources.NoSideNotToMoveCheckMsg, "Board");
             ||}
             */

            #endregion

            return(true);
        }