public Piece PickPiece(SquareE sqr) { Piece p = new Piece(); //bool isPiece = false; for (ColorE color = ColorE.White; color <= ColorE.Black; ++color) { Bitboard occupy = Occupies[(byte)color]; if (BitBoard.GetSquare(occupy, sqr)) { for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type) { Bitboard piece = Pieces[(byte)type]; if (BitBoard.GetSquare(piece, sqr)) // occupy & piece { //Debug.Assert(!isPiece, "Piece Overlaps"); //isPiece = true; return(new Piece(color, type)); } } } } return(p); }
private void ClearSquare(SquareE square) { //bool isPiece = false; for (ColorE color = ColorE.White; color <= ColorE.Black; ++color) { Bitboard occupy = Occupies[(byte)color]; if (BitBoard.GetSquare(occupy, square)) { for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type) { Bitboard piece = Pieces[(byte)type]; if (BitBoard.GetSquare(piece, square)) // occupy & piece { BitBoard.RstSquare(ref Occupies[(byte)color], square); BitBoard.RstSquare(ref Pieces[(byte)type], square); break; //Debug.Assert(!isPiece, "Piece Overlaps"); //isPiece = true; } } } } }
internal static string ToString(Board board) { if (board == default(Board)) { Debug.Assert(false, "Null or Empty FEN"); return(string.Empty); } StringBuilder fenString = new StringBuilder(); #region Pieces for (RankE rank = RankE.Rank_8; ; --rank) { byte emptySqr = 0; for (FileE file = FileE.File_A; file <= FileE.File_H; ++file) { bool isPiece = false; for (ColorE color = ColorE.White; color <= ColorE.Black; ++color) { Bitboard occupy = board.Occupies[(byte)color]; SquareE sqr = Square._Square(file, rank); if (BitBoard.GetSquare(occupy, sqr)) { for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type) { Bitboard piece = board.Pieces[(byte)type]; if (BitBoard.GetSquare(piece, sqr)) // occupy & piece { isPiece = true; if (emptySqr > 0) { fenString.Append(emptySqr); emptySqr = 0; } fenString.Append(Piece.mapPiece[(byte)color, (byte)type]); break; } } } } if (!isPiece) { ++emptySqr; } } if (emptySqr > 0) { fenString.Append(emptySqr); emptySqr = 0; } if (rank == RankE.Rank_1) { break; } fenString.Append(rankSep); } #endregion fenString.Append(recordSep); #region OnMove switch (board.OnMove) { case ColorE.White: fenString.Append('w'); break; case ColorE.Black: fenString.Append('b'); break; case ColorE.NoColor: default: fenString.Append('-'); break; } #endregion fenString.Append(recordSep); #region Castle if (board.Castle[(byte)ColorE.White].AnyCastle || board.Castle[(byte)ColorE.Black].AnyCastle) { if (board.Castle[(byte)ColorE.White].ShortCastle) { fenString.Append('K'); } if (board.Castle[(byte)ColorE.White].LongCastle) { fenString.Append('Q'); } if (board.Castle[(byte)ColorE.Black].ShortCastle) { fenString.Append('k'); } if (board.Castle[(byte)ColorE.Black].LongCastle) { fenString.Append('q'); } } else { fenString.Append('-'); } #endregion fenString.Append(recordSep); #region EnPassant SquareE ep = board.EnPassant; if (Square.IsValid(ep)) { fenString.Append(ep.ToString().ToLower()); } else { fenString.Append('-'); } #endregion fenString.Append(recordSep); #region HalfMove Clock fenString.Append(board.HalfMoveClock); #endregion fenString.Append(recordSep); #region FullMove Counter fenString.Append(board.FullMoveCount); #endregion return(fenString.ToString()); }
/// 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); }
// TODO:: //internal Bitboard AttacksTo( Bitboard occupied, SquareE sqr, ColorE side ) //{ // //Bitboard knights, kings, bishopsQueens, rooksQueens; // //knights = pieceBB[ nWhiteKnight ] | pieceBB[ nBlackKnight ]; // //kings = pieceBB[ nWhiteKing ] | pieceBB[ nBlackKing ]; // //rooksQueens = // //bishopsQueens = pieceBB[ nWhiteQueen ] | pieceBB[ nBlackQueen ]; // //rooksQueens |= pieceBB[ nWhiteRook ] | pieceBB[ nBlackRook ]; // //bishopsQueens |= pieceBB[ nWhiteBishop ] | pieceBB[ nBlackBishop ]; // //return (arrPawnAttacks[ nWhite ][ sqr ] & pieceBB[ nBlackPawn ]) // // | (arrPawnAttacks[ nBlack ][ sqr ] & pieceBB[ nWhitePawn ]) // // | (arrKnightAttacks[ sqr ] & knights) // // | (arrKingAttacks[ sqr ] & kings) // // | (bishopAttacks(occupied, sqr) & bishopsQueens) // // | (rookAttacks(occupied, sqr) & rooksQueens) // // ; // ColorE oppside = ColorE.NoColor; // if( side == ColorE.White ) // { // oppside = ColorE.Black; // } // else if( side == ColorE.Black ) // { // oppside = ColorE.White; // } // Bitboard sideOccupied = Occupies[ (byte) side ]; // Bitboard rooksQueens = Pieces[ (byte) PieceE.Rook ] | Pieces[ (byte) PieceE.Queen ]; // Bitboard bishopsQueens = Pieces[ (byte) PieceE.Bishop ] | Pieces[ (byte) PieceE.Queen ]; // return (MoveAttack._PawnAttacks[ (byte) sqr, (byte) side ] & (Pieces[ (byte) PieceE.Pawn ] & Occupies[ (byte) oppside ])) // | (MoveAttack._PawnAttacks[ (byte) sqr, (byte) oppside ] & (Pieces[ (byte) PieceE.Pawn ] & Occupies[ (byte) side ])) // | (MoveAttack._KnightMoves[ (byte) sqr ] & Pieces[ (byte) PieceE.Knight ]) // | (MoveAttack._KingMoves[ (byte) sqr ] & Pieces[ (byte) PieceE.King ]) // | (MoveAttack._RookMoves[ (byte) sqr ] & rooksQueens) // | (MoveAttack._BishopMoves[ (byte) sqr ] & bishopsQueens); //} public override string ToString() { StringBuilder sboard = new StringBuilder(); sboard.AppendLine(" +-+-+-+-+-+-+-+-+"); //SquareE begSqr = SquareE.A8; //SquareE endSqr = SquareE.H1; //for( SquareE sqr = begSqr; ; Square.BackwardInc(ref sqr) ) //{ // if( (byte) sqr % File.Files == 0 ) // { // if( sqr != begSqr ) sboard.AppendLine(); // sboard.Append(Rank.mapRank[ (byte) sqr / File.Files ]); // } // bool isPiece = false; // sboard.Append(" "); // 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 ]; // if( BitBoard.GetSquare(occupy & piece, sqr) ) // { // //if( isPiece ) sboard.Append('x'); // '*' // isPiece = true; // sboard.Append(Piece.mapPiece[ (byte) color, (byte) type ]); // break; // } // } // } // if( !isPiece ) // sboard.Append("."); // if( sqr == endSqr ) // break; //} for (RankE rank = RankE.Rank_8; ; --rank) { sboard.Append(Rank.mapRank[(byte)rank]); for (FileE file = FileE.File_A; file <= FileE.File_H; ++file) { bool isPiece = false; sboard.Append(" "); for (ColorE color = ColorE.White; color <= ColorE.Black; ++color) { Bitboard occupy = Occupies[(byte)color]; SquareE sqr = Square._Square(file, rank); if (BitBoard.GetSquare(occupy, sqr)) { for (PieceE type = PieceE.Pawn; type <= PieceE.King; ++type) { Bitboard piece = Pieces[(byte)type]; if (BitBoard.GetSquare(piece, sqr)) // occupy & piece { //if( isPiece ) sboard.Append('x'); // '*' isPiece = true; sboard.Append(Piece.mapPiece[(byte)color, (byte)type]); break; } } } } if (!isPiece) { sboard.Append("."); } } if (rank == RankE.Rank_1) { break; } sboard.AppendLine(); } sboard.AppendLine().Append(" +-+-+-+-+-+-+-+-+").AppendLine(); sboard.Append(" "); foreach (char file in File.mapFile) { sboard.Append(" " + file); } return(sboard.ToString()); }
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); }