internal static BitBoard GetKingAttacks(BitBoard king) { BitBoard attacks = CompassRose.OneStepEast(king) | CompassRose.OneStepWest(king); king |= attacks; attacks |= CompassRose.OneStepNorth(king) | CompassRose.OneStepSouth(king); return attacks; }
internal static void Display(BitBoard bitBoard) { for (int r = 7; r >= 0; r--) { Console.WriteLine(" ------------------------"); Console.Write(" {0} ", r + 1); for (int c = 0; c <= 7; c++) { Console.Write('['); if (IsBitSet(bitBoard, Square.GetSquareIndex(c, r))) { Console.ForegroundColor = ConsoleColor.Green; Console.Write('1'); } else { Console.ForegroundColor = ConsoleColor.DarkRed; Console.Write('0'); } Console.ResetColor(); Console.Write(']'); } Console.WriteLine(); } Console.WriteLine("\n A B C D E F G H"); }
private static BitBoard GetDoublePushTargets(byte color, BitBoard pawns, BitBoard empty) { BitBoard singlePush = GetSinglePushTargets(color, pawns, empty); return color == PieceColor.White ? CompassRose.OneStepNorth(singlePush) & empty & Constants.Ranks.Four : CompassRose.OneStepSouth(singlePush) & empty & Constants.Ranks.Five; }
internal static int BitScanForwardReset(ref BitBoard bitBoard) { Debug.Assert(bitBoard.value != 0); UInt64 bb = bitBoard.value; bitBoard.value &= (bitBoard.value - 1); return Constants.DeBrujinTable[((ulong)((long)bb & -(long)bb) * Constants.DeBrujinValue) >> 58]; }
private static BitBoard GetPawnsAbleToSinglePush(byte color, BitBoard pawns, BitBoard empty) { switch (color) { case PieceColor.White: return CompassRose.OneStepSouth(empty) & pawns; case PieceColor.Black: return CompassRose.OneStepNorth(empty) & pawns; default: throw new NotImplementedException(); } }
internal static BitBoard GetAllTargets(byte pieceColor, BitBoard rooks, Board board) { BitBoard occupiedSquares = board.OccupiedSquares; BitBoard targets = Constants.Empty; int square; square = BitBoard.BitScanForward(rooks); targets |= MovePackHelper.GetRankAttacks(occupiedSquares, square); targets |= MovePackHelper.GetFileAttacks(occupiedSquares, square); return targets & ~board.GetPlayerPieces(); }
internal static BitBoard GetAllTargets(byte pieceColor, BitBoard bishops, Board board) { BitBoard occupiedSquares = board.OccupiedSquares; BitBoard targets = Constants.Empty; int square; square = BitBoard.BitScanForward(bishops); targets |= MovePackHelper.GetA1H8DiagonalAttacks(occupiedSquares, square); targets |= MovePackHelper.GetH1A8DiagonalAttacks(occupiedSquares, square); return targets & ~board.GetPlayerPieces(); }
internal static BitBoard GetKnightAttacks(BitBoard knights) { BitBoard west, east, attacks; east = CompassRose.OneStepEast(knights); west = CompassRose.OneStepWest(knights); attacks = (east | west) << 16; attacks |= (east | west) >> 16; east = CompassRose.OneStepEast(east); west = CompassRose.OneStepWest(west); attacks |= (east | west) << 8; attacks |= (east | west) >> 8; return attacks; }
internal static void GetKingMoves(byte color, BitBoard king, Board board, Move[] moveList, ref int pos) { BitBoard targets; byte fromIndex; byte toIndex; while (king != 0) { fromIndex = (byte)BitBoard.BitScanForwardReset(ref king); // search for LS1B and then reset it targets = King.GetAllTargets(color, Constants.SquareMask[fromIndex], board); while (targets != 0) { toIndex = (byte)BitBoard.BitScanForwardReset(ref targets); // search for LS1B and then reset it moveList[pos++] = new Move(fromIndex, toIndex, PieceType.King, board.pieceSet[toIndex].Type, PieceType.None); } } }
private static BitBoard GetPawnsAbleToDoublePush(byte color, BitBoard pawns, BitBoard empty) { switch (color) { case PieceColor.White: { BitBoard emptyRank3 = CompassRose.OneStepSouth(empty & Constants.Ranks.Four) & empty; return GetPawnsAbleToSinglePush(color, pawns, emptyRank3); } case PieceColor.Black: { BitBoard emptyRank6 = CompassRose.OneStepNorth(empty & Constants.Ranks.Six) & empty; return GetPawnsAbleToSinglePush(color, pawns, emptyRank6); } default: throw new NotImplementedException(); } }
internal static int BitScanForward(BitBoard bitBoard) { Debug.Assert(bitBoard.value != 0); return Constants.DeBrujinTable[((ulong)((long)bitBoard.value & -(long)bitBoard.value) * Constants.DeBrujinValue) >> 58]; }
internal static int ToInt32(BitBoard bitBoard) { return (int)bitBoard.value; }
internal static UInt64 GetRankAttacks(BitBoard occupiedSquares, int square) { int rank = Square.GetRankIndex(square); int occupancy = BitBoard.ToInt32((occupiedSquares & Constants.SixBitRankMask[rank]) >> (8 * rank)); return RankAttacks[square][(occupancy >> 1) & 63]; }
internal static UInt64 GetH1A8DiagonalAttacks(BitBoard occupiedSquares, int square) { int diag = Square.GetH1A8AntiDiagonalIndex(square); int occupancy = BitBoard.ToInt32((occupiedSquares & Constants.H1A8DiagonalMask[diag]) * Constants.H1A8DiagonalMagic[diag] >> 56); return H1A8DiagonalAttacks[square][(occupancy >> 1) & 63]; }
internal static BitBoard GetAllTargets(byte color, BitBoard pawns, Board board) { BitBoard empty = board.EmptySquares; return GetQuietTargets(color, pawns, empty) | GetAnyAttack(color, pawns, board); }
internal static BitBoard GetAllTargets(byte pieceColor, BitBoard king, Board board) { BitBoard kingMoves = MovePackHelper.KingAttacks[(BitBoard.BitScanForward(king))]; return kingMoves & ~board.GetPlayerPieces(); }
internal static BitBoard GetAllTargets(byte pieceColor, BitBoard knights, Board board) { BitBoard targets = MovePackHelper.KnightAttacks[(BitBoard.BitScanForward(knights))]; return targets & ~board.GetPlayerPieces(); }
internal static bool IsBitSet(BitBoard bitBoard, int posBit) { return (bitBoard & ((UInt64)1 << (posBit))) != 0; }
private static BitBoard GetWestAttacks(byte color, BitBoard pawns) { return color == PieceColor.White ? CompassRose.OneStepNorthWest(pawns) : CompassRose.OneStepSouthWest(pawns); }
private static BitBoard GetSinglePushTargets(byte color, BitBoard pawns, BitBoard empty) { return color == PieceColor.White ? CompassRose.OneStepNorth(pawns) & empty : CompassRose.OneStepSouth(pawns) & empty; }
private static BitBoard GetQuietTargets(byte color, BitBoard pawns, BitBoard empty) { return GetSinglePushTargets(color, pawns, empty) | GetDoublePushTargets(color, pawns, empty); }
internal static BitBoard GetAnyAttack(byte color, BitBoard pawns, Board board) { return (GetEastAttacks(color, pawns) | GetWestAttacks(color, pawns)) & board.GetEnemyPieces(); }
internal static int PopCount(BitBoard bitBoard) { bitBoard.value -= ((bitBoard.value >> 1) & 0x5555555555555555UL); bitBoard.value = ((bitBoard.value >> 2) & 0x3333333333333333UL) + (bitBoard.value & 0x3333333333333333UL); bitBoard.value = ((bitBoard.value >> 4) + bitBoard.value) & 0x0F0F0F0F0F0F0F0FUL; return (int)((bitBoard.value * 0x0101010101010101UL) >> 56); }
internal static UInt64 GetFileAttacks(BitBoard occupiedSquares, int square) { int file = Square.GetFileIndex(square); int occupancy = BitBoard.ToInt32((occupiedSquares & Constants.SixBitFileMask[file]) * Constants.FileMagic[file] >> 56); return FileAttacks[square][(occupancy >> 1) & 63]; }
private void UpdateGenericBitBoards() { this.WhitePieces = this.bitBoardSet[PieceColor.White][PieceType.Pawn] | this.bitBoardSet[PieceColor.White][PieceType.Knight] | this.bitBoardSet[PieceColor.White][PieceType.Bishop] | this.bitBoardSet[PieceColor.White][PieceType.Rook] | this.bitBoardSet[PieceColor.White][PieceType.Queen] | this.bitBoardSet[PieceColor.White][PieceType.King]; this.BlackPieces = this.bitBoardSet[PieceColor.Black][PieceType.Pawn] | this.bitBoardSet[PieceColor.Black][PieceType.Knight] | this.bitBoardSet[PieceColor.Black][PieceType.Bishop] | this.bitBoardSet[PieceColor.Black][PieceType.Rook] | this.bitBoardSet[PieceColor.Black][PieceType.Queen] | this.bitBoardSet[PieceColor.Black][PieceType.King]; this.OccupiedSquares = WhitePieces | BlackPieces; this.EmptySquares = ~OccupiedSquares; }
internal static BitBoard GetAllTargets(byte pieceColor, BitBoard queens, Board board) { return Rook.GetAllTargets(pieceColor, queens, board) | Bishop.GetAllTargets(pieceColor, queens, board); }
internal void UndoMove(Move move) { //ARRAY this.pieceSet[move.FromSquare] = this.pieceSet[move.ToSquare]; // muove il pezzo this.pieceSet[move.ToSquare] = move.IsCapture() ? new Piece(SideToMove, move.PieceCaptured) : new Piece(PieceColor.None, PieceType.None); // svuota o riempie la casella di partenza //BITBOARDS BitBoard From = Constants.SquareMask[move.FromSquare]; BitBoard To = Constants.SquareMask[move.ToSquare]; BitBoard FromTo = From | To; this.SideToMove = this.SideToMove.GetOpposite(); // aggiorna la bitboard this.bitBoardSet[this.SideToMove][move.PieceMoved] ^= FromTo; if (this.SideToMove == PieceColor.White) this.WhitePieces ^= FromTo; else this.BlackPieces ^= FromTo; if (move.PieceMoved == PieceType.King) this.kingSquare[this.SideToMove] = move.FromSquare; if (move.IsCapture()) { this.bitBoardSet[this.SideToMove.GetOpposite()][move.PieceCaptured] ^= To; //aggiorna i pezzi dell'avversario if (this.SideToMove == PieceColor.White) this.BlackPieces ^= To; else this.WhitePieces ^= To; this.OccupiedSquares ^= From; this.EmptySquares ^= From; } else { this.OccupiedSquares ^= FromTo; this.EmptySquares ^= FromTo; } }
internal bool IsAttacked(BitBoard target, byte side) { BitBoard slidingAttackers; BitBoard pawnAttacks; BitBoard allPieces = this.OccupiedSquares; byte enemyColor = side.GetOpposite(); int to; while (target != 0) { to = BitBoard.BitScanForwardReset(ref target); pawnAttacks = side == PieceColor.White ? MovePackHelper.WhitePawnAttacks[to] : MovePackHelper.BlackPawnAttacks[to]; if ((this.GetPieceSet(enemyColor, PieceType.Pawn) & pawnAttacks) != 0) return true; if ((this.GetPieceSet(enemyColor, PieceType.Knight) & MovePackHelper.KnightAttacks[to]) != 0) return true; if ((this.GetPieceSet(enemyColor, PieceType.King) & MovePackHelper.KingAttacks[to]) != 0) return true; // file / rank attacks slidingAttackers = this.GetPieceSet(enemyColor, PieceType.Queen) | this.GetPieceSet(enemyColor, PieceType.Rook); if (slidingAttackers != 0) { if ((MovePackHelper.GetRankAttacks(allPieces, to) & slidingAttackers) != 0) return true; if ((MovePackHelper.GetFileAttacks(allPieces, to) & slidingAttackers) != 0) return true; } // diagonals slidingAttackers = this.GetPieceSet(enemyColor, PieceType.Queen) | this.GetPieceSet(enemyColor, PieceType.Bishop); if (slidingAttackers != 0) { if ((MovePackHelper.GetH1A8DiagonalAttacks(allPieces, to) & slidingAttackers) != 0) return true; if ((MovePackHelper.GetA1H8DiagonalAttacks(allPieces, to) & slidingAttackers) != 0) return true; } } return false; }
internal bool IsMoveLegal(Move move, BitBoard pinned) { if (move.PieceMoved == PieceType.King) return !this.IsAttacked(Constants.SquareMask[move.ToSquare], this.SideToMove); if (this.IsAttacked(this.bitBoardSet[SideToMove][PieceType.King], this.SideToMove)) { bool islegal = true; this.MakeMove(move); islegal = !this.IsAttacked(this.bitBoardSet[SideToMove.GetOpposite()][PieceType.King], this.SideToMove.GetOpposite()); this.UndoMove(move); return islegal; } return (pinned == 0) || ((pinned & Constants.SquareMask[move.FromSquare]) == 0) || MovePackHelper.AreSquareAligned(move.FromSquare, move.ToSquare, this.kingSquare[this.SideToMove]); }
internal static void GetPawnMoves(byte color, BitBoard pawns, Board board, Move[] moveList, ref int pos) { BitBoard targets; BitBoard epTargets; byte fromIndex; byte toIndex; while (pawns != 0) { fromIndex = (byte)BitBoard.BitScanForwardReset(ref pawns); // search for LS1B and then reset it targets = Pawn.GetAllTargets(color, Constants.SquareMask[fromIndex], board); while (targets != 0) { toIndex = (byte)BitBoard.BitScanForwardReset(ref targets); // search for LS1B and then reset it // en passant if (board.EnPassantSquare != Square.Invalid) { epTargets = color == PieceColor.White ? MovePackHelper.WhitePawnAttacks[fromIndex] : MovePackHelper.BlackPawnAttacks[fromIndex]; if ((epTargets & Constants.SquareMask[board.EnPassantSquare]) != 0) moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, PieceType.Pawn, PieceType.Pawn); } // promotions if (Square.GetRankIndex(toIndex) == 7 && color == PieceColor.White || Square.GetRankIndex(toIndex) == 0 && color == PieceColor.Black) { moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, board.pieceSet[toIndex].Type, PieceType.Queen); moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, board.pieceSet[toIndex].Type, PieceType.Rook); moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, board.pieceSet[toIndex].Type, PieceType.Bishop); moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, board.pieceSet[toIndex].Type, PieceType.Knight); } else moveList[pos++] = new Move(fromIndex, toIndex, PieceType.Pawn, board.pieceSet[toIndex].Type, PieceType.None); // no promotions } } }