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); } } }
/// 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); }
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); }