public static BitBoard XrayRookAttacks(this Square square, BitBoard occupied, BitBoard blockers) { var attacks = square.RookAttacks(occupied); blockers &= attacks; return(attacks ^ square.RookAttacks(occupied ^ blockers)); }
public static BitBoard NorthFill(this BitBoard bb) { bb |= bb << 8; bb |= bb << 16; bb |= bb << 32; return(bb); }
public static BitBoard SouthFill(this BitBoard bb) { bb |= bb >> 8; bb |= bb >> 16; bb |= bb >> 32; return(bb); }
private static EMoveAmbiguity Ambiguity(this Move move, BitBoard similarTypeAttacks, IPosition position) { var ambiguity = EMoveAmbiguity.None; foreach (var square in similarTypeAttacks) { var pinned = position.GetPinnedPieces(square, move.GetMovingSide()); if (similarTypeAttacks & pinned) { continue; } if (move.GetMovingPieceType() != position.GetPieceType(square)) { continue; } if (position.OccupiedBySide[move.GetMovingSide().Side] & square) { if (square.File() == move.GetFromSquare().File()) { ambiguity |= EMoveAmbiguity.File; } else if (square.Rank() == move.GetFromSquare().Rank()) { ambiguity |= EMoveAmbiguity.Rank; } ambiguity |= EMoveAmbiguity.Move; } } return(ambiguity); }
public static Square Lsb(this BitBoard bb) { // @ C author Matt Taylor (2003) bb ^= bb - 1; var folded = (uint)(bb ^ (bb >> 32)); return(Lsb64Table[folded * 0x78291ACF >> 26]); }
public static BitBoard Shift(this BitBoard bb, Direction direction) { if (ShiftFuncs.TryGetValue(direction.Value, out var func)) { return(func(bb)); } throw new ArgumentException("Invalid shift argument.", nameof(direction)); }
static BitBoards() { PseudoAttacksBB = new BitBoard[PieceTypes.PieceTypeNb.AsInt()][]; for (var i = 0; i < PseudoAttacksBB.Length; i++) { PseudoAttacksBB[i] = new BitBoard[64]; } PawnAttackSpanBB = new BitBoard[2][]; PawnAttackSpanBB[0] = new BitBoard[64]; PawnAttackSpanBB[1] = new BitBoard[64]; PassedPawnMaskBB = new BitBoard[2][]; PassedPawnMaskBB[0] = new BitBoard[64]; PassedPawnMaskBB[1] = new BitBoard[64]; ForwardRanksBB = new BitBoard[2][]; ForwardRanksBB[0] = new BitBoard[64]; ForwardRanksBB[1] = new BitBoard[64]; ForwardFileBB = new BitBoard[2][]; ForwardFileBB[0] = new BitBoard[64]; ForwardFileBB[1] = new BitBoard[64]; KingRingBB = new BitBoard[2][]; KingRingBB[0] = new BitBoard[64]; KingRingBB[1] = new BitBoard[64]; BetweenBB = new BitBoard[64][]; for (var i = 0; i < BetweenBB.Length; i++) { BetweenBB[i] = new BitBoard[64]; } LineBB = new BitBoard[64][]; for (var i = 0; i < LineBB.Length; i++) { LineBB[i] = new BitBoard[64]; } SquareDistance = new int[64][]; for (var i = 0; i < SquareDistance.Length; i++) { SquareDistance[i] = new int[64]; } DistanceRingBB = new BitBoard[64][]; for (var i = 0; i < SquareDistance.Length; i++) { DistanceRingBB[i] = new BitBoard[8]; } CornerA1 = MakeBitboard(Squares.a1, Squares.b1, Squares.a2, Squares.b2); CornerA8 = MakeBitboard(Squares.a8, Squares.b8, Squares.a7, Squares.b7); CornerH1 = MakeBitboard(Squares.h1, Squares.g1, Squares.h2, Squares.g2); CornerH8 = MakeBitboard(Squares.h8, Squares.g8, Squares.h7, Squares.g7);
public static void ToString(this BitBoard bb, TextWriter outputWriter) { try { outputWriter.WriteLine(bb); } catch (IOException ioException) { throw new IOException("Writer is not available.", ioException); } }
public static int PopCount(BitBoard bb) { var y = 0; while (bb) { y++; ResetLsb(ref bb); } return(y); }
public static Square Msb(this BitBoard bb) { const ulong debruijn64 = 0x03f79d71b4cb0a89UL; bb |= bb >> 1; bb |= bb >> 2; bb |= bb >> 4; bb |= bb >> 8; bb |= bb >> 16; bb |= bb >> 32; return(Msb64Table[(bb.Value * debruijn64) >> 58]); }
public static BitBoard GetAttacks(this Square square, EPieceType pieceType, BitBoard occupied = new BitBoard()) { return(pieceType == EPieceType.Knight || pieceType == EPieceType.King ? PseudoAttacksBB[pieceType.AsInt(), square.AsInt()] : pieceType == EPieceType.Bishop ? square.BishopAttacks(occupied) : pieceType == EPieceType.Rook ? square.RookAttacks(occupied) : pieceType == EPieceType.Queen ? square.QueenAttacks(occupied) : Zero); }
public static BitBoard MakeBitboard(params Square[] squares) { BitBoard b = ZeroBb; // ReSharper disable once ForCanBeConvertedToForeach // ReSharper disable once LoopCanBeConvertedToQuery for (var i = 0; i < squares.Length; ++i) { b |= squares[i]; } return(b); }
public static BitBoard XrayAttacks(this Square square, EPieceType pieceType, BitBoard occupied, BitBoard blockers) { switch (pieceType) { case EPieceType.Bishop: return(square.XrayBishopAttacks(occupied, blockers)); case EPieceType.Rook: return(square.XrayRookAttacks(occupied, blockers)); case EPieceType.Queen: return(XrayBishopAttacks(square, occupied, blockers) | XrayRookAttacks(square, occupied, blockers)); default: return(EmptyBitBoard); } }
public static BitBoard GetAttacks(this Square square, EPieceType pieceType, BitBoard occupied = new BitBoard()) { switch (pieceType) { case EPieceType.Knight: case EPieceType.King: return(PseudoAttacksBB[pieceType.AsInt(), square.AsInt()]); case EPieceType.Bishop: return(square.BishopAttacks(occupied)); case EPieceType.Rook: return(square.RookAttacks(occupied)); case EPieceType.Queen: return(square.QueenAttacks(occupied)); default: return(EmptyBitBoard); } }
public static string PrintBitBoard(BitBoard b, string title = "") { var s = new StringBuilder("+---+---+---+---+---+---+---+---+---+\n", 1024); if (!string.IsNullOrWhiteSpace(title)) { s.AppendLine($"| {title}"); } for (var r = ERank.Rank8; r >= ERank.Rank1; --r) { s.AppendFormat("| {0} ", (int)r + 1); for (var f = EFile.FileA; f <= EFile.FileH; ++f) { s.AppendFormat("| {0} ", (b & new Square(r, f)).Empty() ? ' ' : 'X'); } s.AppendLine("|\n+---+---+---+---+---+---+---+---+---+"); } s.AppendLine("| | A | B | C | D | E | F | G | H |"); s.AppendLine("+---+---+---+---+---+---+---+---+---+"); return(s.ToString()); }
public static BitBoard NorthWestOne(this BitBoard bb) => (bb & ~FILEA) << 7;
public static BitBoard SouthWestOne(this BitBoard bb) => (bb & ~FILEA) >> 9;
public static BitBoard SouthEastOne(this BitBoard bb) => (bb & ~FILEH) >> 7;
public static bool IsSet(this BitBoard bb, int pos) => (bb.Value & (One << pos)) != 0;
public static Square Last(this BitBoard bb) => bb.Msb();
public static Square First(this BitBoard bb) => bb.Lsb();
public static BitBoard NorthEastOne(this BitBoard bb) => (bb & ~FILEH) << 9;
static BitBoards() { QueenSide = new BitBoard(FILEA | FILEB | FILEC | FILED); CenterFiles = new BitBoard(FILEC | FILED | FILEE | FILEF); KingSide = new BitBoard(FILEE | FILEF | FILEG | FILEH); Center = new BitBoard((FILED | FILEE) & (RANK4 | RANK5)); ShiftFuncs = MakeShiftFuncs(); BetweenBB = new BitBoard[64, 64]; PseudoAttacksBB = new BitBoard[EPieceType.PieceTypeNb.AsInt(), 64]; EmptyBitBoard = new BitBoard(ZeroBb); AllSquares = ~EmptyBitBoard; PawnAttackSpanBB = new BitBoard[2, 64]; PassedPawnMaskBB = new BitBoard[2, 64]; ForwardRanksBB = new BitBoard[2, 64]; ForwardFileBB = new BitBoard[2, 64]; LineBB = new BitBoard[64, 64]; KingRingBB = new BitBoard[2, 64]; SquareDistance = new byte[64, 64]; DistanceRingBB = new BitBoard[64, 8]; // local helper functions to calculate distance int distance(int x, int y) { return(Math.Abs(x - y)); } int distanceFile(Square x, Square y) { return(distance(x.File().AsInt(), y.File().AsInt())); } int distanceRank(Square x, Square y) { return(distance(x.Rank().AsInt(), y.Rank().AsInt())); } var validMagicPieces = new[] { EPieceType.Bishop, EPieceType.Rook }; // ForwardRanksBB population loop idea from sf for (var r = ERank.Rank1; r < ERank.RankNb; ++r) { var rank = (int)r; ForwardRanksBB[0, rank] = ~(ForwardRanksBB[1, rank + 1] = ForwardRanksBB[1, rank] | RankBB[rank]); } for (var side = EPlayer.White; side < EPlayer.PlayerNb; ++side) { var c = (int)side; foreach (var square in AllSquares) { var s = square.AsInt(); ForwardFileBB[c, s] = ForwardRanksBB[c, square.Rank().AsInt()] & FileBB[square.File().AsInt()]; PawnAttackSpanBB[c, s] = ForwardRanksBB[c, square.Rank().AsInt()] & AdjacentFilesBB[square.File().AsInt()]; PassedPawnMaskBB[c, s] = ForwardFileBB[c, s] | PawnAttackSpanBB[c, s]; } } // mini local helpers BitBoard ComputeKnightAttack(BitBoard b) { BitBoard res = (b & ~(FILEA | FILEB)) << 6; res |= (b & ~FILEA) << 15; res |= (b & ~FILEH) << 17; res |= (b & ~(FILEG | FILEH)) << 10; res |= (b & ~(FILEG | FILEH)) >> 6; res |= (b & ~FILEH) >> 15; res |= (b & ~FILEA) >> 17; res |= (b & ~(FILEA | FILEB)) >> 10; return(res); } // Pseudo attacks for all pieces foreach (var s1 in AllSquares) { var sq = s1.AsInt(); var b = s1.BitBoardSquare(); var file = s1.File(); // distance computation foreach (var s2 in AllSquares) { SquareDistance[sq, s2.AsInt()] = (byte)distanceFile(s1, s2).Max(distanceRank(s1, s2)); DistanceRingBB[sq, SquareDistance[sq, s2.AsInt()]] |= s2; } PseudoAttacksBB[0, sq] = b.NorthEastOne() | b.NorthWestOne(); PseudoAttacksBB[1, sq] = b.SouthWestOne() | b.SouthEastOne(); var pt = EPieceType.Knight.AsInt(); PseudoAttacksBB[pt, sq] = ComputeKnightAttack(b); var bishopAttacks = s1.BishopAttacks(EmptyBitBoard); var rookAttacks = s1.RookAttacks(EmptyBitBoard); pt = EPieceType.Bishop.AsInt(); PseudoAttacksBB[pt, sq] = bishopAttacks; pt = EPieceType.Rook.AsInt(); PseudoAttacksBB[pt, sq] = rookAttacks; pt = EPieceType.Queen.AsInt(); PseudoAttacksBB[pt, sq] = bishopAttacks | rookAttacks; pt = EPieceType.King.AsInt(); PseudoAttacksBB[pt, sq] = b.NorthOne() | b.SouthOne() | b.EastOne() | b.WestOne() | b.NorthEastOne() | b.NorthWestOne() | b.SouthEastOne() | b.SouthWestOne(); // Compute lines and betweens foreach (var validMagicPiece in validMagicPieces) { pt = validMagicPiece.AsInt(); foreach (var s2 in AllSquares) { if ((PseudoAttacksBB[pt, sq] & s2).Empty()) { continue; } LineBB[sq, s2.AsInt()] = GetAttacks(s1, validMagicPiece, EmptyBitBoard) & GetAttacks(s2, validMagicPiece, EmptyBitBoard) | s1 | s2; BetweenBB[sq, s2.AsInt()] = GetAttacks(s1, validMagicPiece, BbSquares[s2.AsInt()]) & GetAttacks(s2, validMagicPiece, BbSquares[sq]); } } // Compute KingRings pt = EPieceType.King.AsInt(); for (var side = EPlayer.White; side < EPlayer.PlayerNb; ++side) { var c = (int)side; KingRingBB[c, sq] = PseudoAttacksBB[pt, sq]; if (s1.RelativeRank(side) == ERank.Rank1) { KingRingBB[c, sq] |= KingRingBB[c, sq].Shift(side == EPlayer.White ? EDirection.North : EDirection.South); } if (file == EFile.FileH) { KingRingBB[c, sq] |= KingRingBB[c, sq].WestOne(); } else if (file == EFile.FileA) { KingRingBB[c, sq] |= KingRingBB[c, sq].EastOne(); } Debug.Assert(!KingRingBB[c, sq].Empty()); } } CornerA1 = MakeBitboard(ESquare.a1, ESquare.b1, ESquare.a2, ESquare.b2); CornerA8 = MakeBitboard(ESquare.a8, ESquare.b8, ESquare.a7, ESquare.b7); CornerH1 = MakeBitboard(ESquare.h1, ESquare.g1, ESquare.h2, ESquare.g2); CornerH8 = MakeBitboard(ESquare.h8, ESquare.g8, ESquare.h7, ESquare.g7); }
public static BitBoard SouthOne(this BitBoard bb) => bb >> 8;
public static BitBoard Fill(this BitBoard bb, Player side) => side == EPlayer.White ? bb.NorthFill() : bb.SouthFill();
public static BitBoard EastOne(this BitBoard bb) => (bb & ~FILEH) << 1;
public static void ResetLsb(ref BitBoard bb) => bb &= bb - 1;
public static BitBoard WestOne(this BitBoard bb) => (bb & ~FILEA) >> 1;
public static BitBoard NorthOne(this BitBoard bb) => bb << 8;
public static Square Get(this BitBoard bb, int pos) => (int)(bb.Value >> pos) & 0x1;