/// <summary> /// Calculates attacks for the specified piece. /// </summary> /// <param name="pieceBitboard">The bitboard with set bit at piece position.</param> /// <param name="excludedFields">The bitboard with excluded fields from attacks calculating.</param> /// <param name="opt">The generator parameters.</param> private static void CalculateAttacks(ulong pieceBitboard, ulong excludedFields, GeneratorParameters opt) { if ((opt.Mode & GeneratorMode.CalculateAttacks) == 0) { return; } var pieceIndex = BitOperations.GetBitIndex(pieceBitboard); var blockersToRemove = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Bishop)] | opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Queen)]; var allPiecesOccupancy = opt.OccupancySummary & ~blockersToRemove; var pattern = MagicContainer.GetBishopAttacks(pieceIndex, allPiecesOccupancy); pattern = CalculatePawnBlockers(pieceIndex, pattern, opt); pattern ^= excludedFields; while (pattern != 0) { var patternLSB = BitOperations.GetLSB(pattern); pattern = BitOperations.PopLSB(pattern); var patternIndex = BitOperations.GetBitIndex(patternLSB); opt.Bitboard.Attacks[patternIndex] |= pieceBitboard; opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB; } }
/// <summary> /// Checks if there is a G4/G5 sacrifice pattern (enemy sacrifice light piece to open file near to the king and /// attack him with the Queen/Rook). /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="move">The move.</param> /// <returns>True if patterns is detected and move should be pruned, otherwise false.</returns> private bool IsG4G5Sacrifice(Bitboard bitboard, Move move) { const ulong whiteTrapField = 0x0000000200000000; const ulong blackTrapField = 0x0000000002000000; var castlingDone = bitboard.CastlingDone[(int)move.Color]; var regularGamePhase = bitboard.GamePhase == GamePhase.Regular; var moveDetected = false; var lightPieceDetected = false; var whitePiecesTrap = bitboard.Pieces[FastArray.GetPieceIndex(Color.White, PieceType.Knight)] | bitboard.Pieces[FastArray.GetPieceIndex(Color.White, PieceType.Bishop)]; var blackPiecesTrap = bitboard.Pieces[FastArray.GetPieceIndex(Color.Black, PieceType.Knight)] | bitboard.Pieces[FastArray.GetPieceIndex(Color.Black, PieceType.Bishop)]; switch (move.Color) { case Color.White: { moveDetected = move.From == new Position(8, 3) && move.To == new Position(7, 4); lightPieceDetected = (blackPiecesTrap & blackTrapField) != 0; break; } case Color.Black: { moveDetected = move.From == new Position(8, 6) && move.To == new Position(7, 5); lightPieceDetected = (whitePiecesTrap & whiteTrapField) != 0; break; } } return(castlingDone && regularGamePhase && moveDetected && lightPieceDetected); }
/// <summary> /// Removes en passant piece from the specified bitboard. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="enemyColor">The enemy color.</param> /// <param name="fieldLSB">The bitboard with set field.</param> private void RemoveEnPassantPiece(Bitboard bitboard, Color enemyColor, ulong fieldLSB) { var enPassantPiece = Color == Color.White ? fieldLSB >> 8 : fieldLSB << 8; bitboard.Pieces[FastArray.GetPieceIndex(enemyColor, PieceType.Pawn)] &= ~enPassantPiece; bitboard.Occupancy[(int)enemyColor] ^= enPassantPiece; IncrementalMaterial.RemovePiece(bitboard, enemyColor, PieceType.Pawn); IncrementalPosition.RemovePiece(bitboard, enemyColor, PieceType.Pawn, enPassantPiece); IncrementalZobrist.AddOrRemovePiece(enemyColor, PieceType.Pawn, enPassantPiece, bitboard); }
/// <summary> /// Checks if king with the specified color is checked. /// </summary> /// <param name="color">The king color.</param> /// <returns>True if king with specified color is checked, otherwise false.</returns> public bool IsCheck(Color color) { if (!_calculated) { throw new BitboardNotCalculatedException(); } var enemyColor = ColorOperations.Invert(color); var king = Pieces[FastArray.GetPieceIndex(color, PieceType.King)]; return((AttacksSummary[(int)enemyColor] & king) != 0); }
/// <summary> /// Gets a pieces array (for bitboards). /// </summary> /// <returns>The pieces array.</returns> public ulong[] GetPiecesArray() { var pieces = new ulong[12]; foreach (var piece in Pieces) { var bitPosition = BitPositionConverter.ToULong(piece.Position); pieces[FastArray.GetPieceIndex(piece.Color, piece.Type)] |= bitPosition; } return(pieces); }
/// <summary> /// Calculates occupancy for all players. /// </summary> /// <returns>The occupancy array.</returns> private ulong[] CalculateOccupancy() { var occupancy = new ulong[2]; for (var piece = 0; piece < 6; piece++) { occupancy[(int)Color.White] |= Pieces[FastArray.GetPieceIndex(Color.White, (PieceType)piece)]; occupancy[(int)Color.Black] |= Pieces[FastArray.GetPieceIndex(Color.Black, (PieceType)piece)]; } return(occupancy); }
/// <summary> /// Calculates a position evaluation result for the specified parameters. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The position evaluation result.</returns> private int GetPosition(Bitboard bitboard, Color color) { var position = 0; for (var piece = 0; piece < 6; piece++) { var piecesToParse = bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)]; position += GetPositionValue(bitboard, color, (PieceType)piece, piecesToParse); } return(position); }
/// <summary> /// Gets a piece type on the specified field. /// </summary> /// <param name="field">The field with piece.</param> /// <param name="pieceColor">The piece color.</param> /// <param name="bitboard">The bitboard.</param> /// <exception cref="PieceTypeNotFoundException">Thrown when there is no piece on the specified field.</exception> /// <returns>The piece type on the specified field.</returns> private PieceType GetPieceType(ulong field, Color pieceColor, Bitboard bitboard) { for (var piece = 0; piece < 6; piece++) { if ((field & bitboard.Pieces[FastArray.GetPieceIndex(pieceColor, (PieceType)piece)]) != 0) { return((PieceType)piece); } } throw new PieceTypeNotFoundException(); }
/// <summary> /// Calculates diagonal attacks (and moves if possible). /// </summary> /// <param name="leftAttackShift">The left attack shift.</param> /// <param name="rightAttackShift">The right attacks shift.</param> /// <param name="ignoreFields">The bitboard with fields to ignore (white and black pieces will have different ones).</param> /// <param name="opt">The generator parameters.</param> private static void CalculateDiagonalAttacks(int leftAttackShift, int rightAttackShift, ulong ignoreFields, GeneratorParameters opt) { var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)]; var validPieces = piecesToParse & ~ignoreFields; var pattern = opt.FriendlyColor == Color.White ? validPieces << leftAttackShift : validPieces >> rightAttackShift; var promotionLine = GetPromotionLine(opt.FriendlyColor); while (pattern != 0) { var patternLSB = BitOperations.GetLSB(pattern); pattern = BitOperations.PopLSB(pattern); var patternIndex = BitOperations.GetBitIndex(patternLSB); var pieceLSB = opt.FriendlyColor == Color.White ? patternLSB >> leftAttackShift : patternLSB << rightAttackShift; var pieceIndex = BitOperations.GetBitIndex(pieceLSB); if ((opt.Mode & GeneratorMode.CalculateMoves) != 0) { var piecePosition = BitPositionConverter.ToPosition(pieceIndex); var enPassantField = opt.Bitboard.EnPassant[(int)opt.EnemyColor] & patternLSB; if ((patternLSB & opt.EnemyOccupancy) != 0 || enPassantField != 0) { var to = BitPositionConverter.ToPosition(patternIndex); if (enPassantField != 0) { opt.Bitboard.Moves.AddLast(new EnPassantMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor)); } else if ((patternLSB & promotionLine) != 0) { opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Queen, true)); opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Rook, true)); opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Bishop, true)); opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Knight, true)); } else { opt.Bitboard.Moves.AddLast(new KillMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor)); } } } if ((opt.Mode & GeneratorMode.CalculateAttacks) != 0) { opt.Bitboard.Attacks[patternIndex] |= pieceLSB; opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB; } } }
/// <summary> /// Generates available moves. /// </summary> /// <param name="pieceType">The piece type.</param> /// <param name="opt">The generator parameters.</param> public static void Generate(PieceType pieceType, GeneratorParameters opt) { var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, pieceType)]; while (piecesToParse != 0) { var pieceLSB = BitOperations.GetLSB(piecesToParse); piecesToParse = BitOperations.PopLSB(piecesToParse); var excludeFromAttacks = CalculateMoves(pieceType, pieceLSB, opt); CalculateAttacks(pieceLSB, excludeFromAttacks, opt); } }
/// <summary> /// Calculates a material evaluation result for the specified player by adding all piece values and /// multiplying them by the specified ratio. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The material evaluation result for the specified player.</returns> private int GetMaterialValue(Bitboard bitboard, Color color) { var material = 0; for (var piece = 0; piece < 6; piece++) { var piecesToParse = bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)]; var piecesCount = BitOperations.Count(piecesToParse); material += piecesCount * MaterialValues.PieceValues[piece]; } return(material); }
/// <summary> /// Gets a least valuable piece for the specified bitboard with field attackers. /// </summary> /// <param name="attackers">The bitboard with field attackers.</param> /// <param name="color">The color of a least valuable piece.</param> /// <param name="bitboard">The bitboard.</param> /// <returns>The least valuable piece (null if there is no more available pieces).</returns> private PieceType?GetAndPopLeastValuablePiece(ref ulong attackers, Color color, Bitboard bitboard) { for (var piece = 0; piece < 6; piece++) { var attackersWithType = attackers & bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)]; if (attackersWithType != 0) { var attackerLSB = BitOperations.GetLSB(attackersWithType); attackers &= ~attackerLSB; return((PieceType)piece); } } return(null); }
/// <summary> /// Helper method for derived classes, calculates move with the specified parameters. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="pieceFrom">The source piece type.</param> /// <param name="from">The piece source position.</param> /// <param name="pieceTo">The destination piece type.</param> /// <param name="to">The piece destination position.</param> protected void CalculatePieceMove(Bitboard bitboard, PieceType pieceFrom, ulong from, PieceType pieceTo, ulong to) { bitboard.Pieces[FastArray.GetPieceIndex(Color, pieceFrom)] &= ~from; bitboard.Pieces[FastArray.GetPieceIndex(Color, pieceTo)] |= to; bitboard.Occupancy[(int)Color] ^= from | to; IncrementalPosition.RemovePiece(bitboard, Color, pieceFrom, from); IncrementalPosition.AddPiece(bitboard, Color, pieceTo, to); IncrementalZobrist.AddOrRemovePiece(Color, pieceFrom, from, bitboard); IncrementalZobrist.AddOrRemovePiece(Color, pieceTo, to, bitboard); if (pieceFrom == PieceType.Pawn) { bitboard.ReversibleMoves = 0; } }
/// <summary> /// Calculates X-Ray attacks when friendly pawn is on bishop way. /// </summary> /// <param name="pieceIndex">The field index with the specified bishop.</param> /// <param name="pattern">The bishop moves pattern.</param> /// <param name="opt">The generator parameters.</param> /// <returns>The attacks bitboard with pawn X-Ray attacks.</returns> private static ulong CalculatePawnBlockers(int pieceIndex, ulong pattern, GeneratorParameters opt) { var patternWithFriendlyBlockers = pattern; var allowedBlockers = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)]; var piecePosition = BitPositionConverter.ToPosition(pieceIndex); var friendlyBlockers = pattern & opt.FriendlyOccupancy & allowedBlockers; while (friendlyBlockers != 0) { var friendlyBlockerLSB = BitOperations.GetLSB(friendlyBlockers); friendlyBlockers = BitOperations.PopLSB(friendlyBlockers); var friendlyBlockerIndex = BitOperations.GetBitIndex(friendlyBlockerLSB); var friendlyBlockerPosition = BitPositionConverter.ToPosition(friendlyBlockerIndex); switch (opt.FriendlyColor) { case Color.White when friendlyBlockerPosition.X > piecePosition.X && friendlyBlockerPosition.Y > piecePosition.Y && (friendlyBlockerLSB & (BitConstants.HFile | BitConstants.HRank)) == 0: { patternWithFriendlyBlockers |= friendlyBlockerLSB << 7; break; } case Color.White when friendlyBlockerPosition.X <piecePosition.X && friendlyBlockerPosition.Y> piecePosition.Y && (friendlyBlockerLSB & (BitConstants.AFile | BitConstants.HRank)) == 0: { patternWithFriendlyBlockers |= friendlyBlockerLSB << 9; break; } case Color.Black when friendlyBlockerPosition.X > piecePosition.X && friendlyBlockerPosition.Y < piecePosition.Y && (friendlyBlockerLSB & (BitConstants.HFile | BitConstants.ARank)) == 0: { patternWithFriendlyBlockers |= friendlyBlockerLSB >> 9; break; } case Color.Black when friendlyBlockerPosition.X < piecePosition.X && friendlyBlockerPosition.Y < piecePosition.Y && (friendlyBlockerLSB & (BitConstants.AFile | BitConstants.ARank)) == 0: { patternWithFriendlyBlockers |= friendlyBlockerLSB >> 7; break; } } } return(patternWithFriendlyBlockers); }
/// <summary> /// Removes killed piece from the specified bitboard. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="enemyColor">The enemy color.</param> /// <param name="fieldLSB">The bitboard with set field.</param> protected void CalculateKill(Bitboard bitboard, Color enemyColor, ulong fieldLSB) { for (var piece = 0; piece < 6; piece++) { var index = FastArray.GetPieceIndex(enemyColor, (PieceType)piece); if ((bitboard.Pieces[index] & fieldLSB) != 0) { bitboard.Pieces[index] &= ~fieldLSB; bitboard.Occupancy[(int)enemyColor] &= ~fieldLSB; IncrementalMaterial.RemovePiece(bitboard, enemyColor, (PieceType)piece); IncrementalPosition.RemovePiece(bitboard, enemyColor, (PieceType)piece, fieldLSB); IncrementalZobrist.AddOrRemovePiece(enemyColor, (PieceType)piece, fieldLSB, bitboard); bitboard.ReversibleMoves = 0; break; } } }
/// <summary> /// Calculates a chain evaluation result for the specified player by adding number of pawns /// in chains multiplied by the specified ratio. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The chain evaluation result for the specified player.</returns> public int GetChainValue(Bitboard bitboard, Color color) { var chain = 0; var pawns = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)]; var pawnsToParse = pawns; while (pawnsToParse != 0) { var pawnLSB = BitOperations.GetLSB(pawnsToParse); pawnsToParse = BitOperations.PopLSB(pawnsToParse); var chainMask = GetChainMask(color, pawnLSB); chain += BitOperations.Count(pawns & chainMask); } return(chain * PawnStructureValues.PawnChainRatio[(int)bitboard.GamePhase]); }
/// <summary> /// Generates available moves. /// </summary> /// <param name="opt">The generator parameters.</param> public static void Generate(GeneratorParameters opt) { var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Knight)]; while (piecesToParse != 0) { var pieceLSB = BitOperations.GetLSB(piecesToParse); piecesToParse = BitOperations.PopLSB(piecesToParse); var pieceIndex = BitOperations.GetBitIndex(pieceLSB); var piecePosition = BitPositionConverter.ToPosition(pieceIndex); var pattern = PatternsContainer.KnightPattern[pieceIndex]; while (pattern != 0) { var patternLSB = BitOperations.GetLSB(pattern); pattern = BitOperations.PopLSB(pattern); var patternIndex = BitOperations.GetBitIndex(patternLSB); if ((opt.Mode & GeneratorMode.CalculateMoves) != 0 && (patternLSB & opt.FriendlyOccupancy) == 0) { var to = BitPositionConverter.ToPosition(patternIndex); if ((patternLSB & opt.EnemyOccupancy) == 0 && !opt.QuiescenceSearch) { opt.Bitboard.Moves.AddLast(new QuietMove(piecePosition, to, PieceType.Knight, opt.FriendlyColor)); } else if ((patternLSB & opt.EnemyOccupancy) != 0) { opt.Bitboard.Moves.AddLast(new KillMove(piecePosition, to, PieceType.Knight, opt.FriendlyColor)); } } if ((opt.Mode & GeneratorMode.CalculateAttacks) != 0) { opt.Bitboard.Attacks[patternIndex] |= pieceLSB; opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB; } } } }
/// <summary> /// Calculates double push moves. /// </summary> /// <param name="opt">The generator parameters.</param> private static void CalculateMovesForDoublePush(GeneratorParameters opt) { if ((opt.Mode & GeneratorMode.CalculateMoves) == 0 || opt.QuiescenceSearch) { return; } var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)]; ulong validPieces; ulong pattern; if (opt.FriendlyColor == Color.White) { validPieces = piecesToParse & BitConstants.BRank; validPieces &= ~opt.OccupancySummary >> 8; pattern = validPieces << 16; } else { validPieces = piecesToParse & BitConstants.GRank; validPieces &= ~opt.OccupancySummary << 8; pattern = validPieces >> 16; } pattern &= ~opt.OccupancySummary; while (pattern != 0) { var patternLSB = BitOperations.GetLSB(pattern); pattern = BitOperations.PopLSB(pattern); var patternIndex = BitOperations.GetBitIndex(patternLSB); var pieceLSB = opt.FriendlyColor == Color.White ? patternLSB >> 16 : patternLSB << 16; var pieceIndex = BitOperations.GetBitIndex(pieceLSB); var from = BitPositionConverter.ToPosition(pieceIndex); var to = BitPositionConverter.ToPosition(patternIndex); opt.Bitboard.Moves.AddLast(new QuietMove(from, to, PieceType.Pawn, opt.FriendlyColor)); } }
/// <summary> /// Calculates a doubled pawns evaluation result for the specified player by adding number of pawns /// on the same files. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The doubled pawns evaluation result for the specified player.</returns> public int GetDoubledPawnsValue(Bitboard bitboard, Color color) { var doubledPawns = 0; var pawns = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)]; for (var i = 0; i < 8; i++) { var file = BitConstants.HFile << i; var pawnsInFile = pawns & file; pawnsInFile = BitOperations.PopLSB(pawnsInFile); if (pawnsInFile != 0) { doubledPawns += BitOperations.Count(pawnsInFile); } } return(doubledPawns * PawnStructureValues.DoubledPawnsRatio[(int)bitboard.GamePhase]); }
/// <summary> /// Calculates single push moves. /// </summary> /// <param name="opt">The generator parameters.</param> private static void CalculateMovesForSinglePush(GeneratorParameters opt) { if ((opt.Mode & GeneratorMode.CalculateMoves) == 0) { return; } var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)]; var promotionLine = GetPromotionLine(opt.FriendlyColor); var pattern = opt.FriendlyColor == Color.White ? piecesToParse << 8 : piecesToParse >> 8; pattern &= ~opt.OccupancySummary; while (pattern != 0) { var patternLSB = BitOperations.GetLSB(pattern); pattern = BitOperations.PopLSB(pattern); var patternIndex = BitOperations.GetBitIndex(patternLSB); var pieceLSB = opt.FriendlyColor == Color.White ? patternLSB >> 8 : patternLSB << 8; var pieceIndex = BitOperations.GetBitIndex(pieceLSB); var from = BitPositionConverter.ToPosition(pieceIndex); var to = BitPositionConverter.ToPosition(patternIndex); if ((patternLSB & promotionLine) == 0 && !opt.QuiescenceSearch) { opt.Bitboard.Moves.AddLast(new QuietMove(from, to, PieceType.Pawn, opt.FriendlyColor)); } else if ((patternLSB & promotionLine) != 0) { opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Queen, false)); opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Rook, false)); opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Bishop, false)); opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Knight, false)); } } }
/// <summary> /// Calculates a value of pieces that are attacking the neighbour fields of specified king. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The king color.</param> /// <returns>The value of the pieces that are attacking king neighbour fields multiplied by the specified ratio.</returns> private int GetAttackedNeighboursValue(Bitboard bitboard, Color color) { var attackedNeighbours = 0; var king = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.King)]; var kingIndex = BitOperations.GetBitIndex(king); var kingMoves = PatternsContainer.KingExpandedPattern[kingIndex]; while (kingMoves != 0) { var fieldLSB = BitOperations.GetLSB(kingMoves); kingMoves = BitOperations.PopLSB(kingMoves); var fieldIndex = BitOperations.GetBitIndex(fieldLSB); var attacks = bitboard.Attacks[fieldIndex] & ~bitboard.Occupancy[(int)color]; attackedNeighbours += BitOperations.Count(attacks); } return(attackedNeighbours * KingSafetyValues.AttackedNeighboursRatio[(int)bitboard.GamePhase]); }
/// <summary> /// Calculates a isolated pawns evaluation result for the specified player by adding number of pawns /// without any same-color pawns at neighbour files. /// </summary> /// <param name="bitboard">The bitboard.</param> /// <param name="color">The player color.</param> /// <returns>The isolated pawns evaluation result for the specified player.</returns> public int GetIsolatedPawnsValue(Bitboard bitboard, Color color) { var isolatedPawns = 0; var pawns = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)]; for (var i = 0; i < 8; i++) { var file = BitConstants.HFile << i; var pawnsInFile = pawns & file; var previousLinePawns = pawns & ((file & ~BitConstants.AFile) << 1); var nextLinePawns = pawns & ((file & ~BitConstants.HFile) >> 1); if (pawnsInFile != 0 && previousLinePawns == 0 && nextLinePawns == 0) { isolatedPawns += BitOperations.Count(pawnsInFile); } } return(isolatedPawns * PawnStructureValues.IsolatedPawnsRatio[(int)bitboard.GamePhase]); }
/// <summary> /// Gets a piece type on the specified field. /// </summary> /// <param name="field">The field with piece.</param> /// <param name="pieceColor">The piece color.</param> /// <param name="bitboard">The bitboard.</param> /// <exception cref="PieceTypeNotFoundException">Thrown when there is no piece on the specified field.</exception> /// <returns>The piece type on the specified field.</returns> private PieceType GetPieceType(ulong field, Color pieceColor, Bitboard bitboard) { for (var piece = 0; piece < 6; piece++) { if ((field & bitboard.Pieces[FastArray.GetPieceIndex(pieceColor, (PieceType)piece)]) != 0) { return((PieceType)piece); } } // Temporary, there is a bug here Console.WriteLine(field); Console.WriteLine(pieceColor); Console.WriteLine(bitboard.Occupancy[0]); Console.WriteLine(bitboard.Occupancy[1]); Console.WriteLine(bitboard.AttacksSummary[0]); Console.WriteLine(bitboard.AttacksSummary[1]); Console.WriteLine(bitboard.VerifyIntegrity()); Console.WriteLine(bitboard.Pieces[0]); Console.WriteLine(bitboard.Pieces[1]); Console.WriteLine(bitboard.Pieces[2]); Console.WriteLine(bitboard.Pieces[3]); Console.WriteLine(bitboard.Pieces[4]); Console.WriteLine(bitboard.Pieces[5]); Console.WriteLine(bitboard.Pieces[6]); Console.WriteLine(bitboard.Pieces[7]); Console.WriteLine(bitboard.Pieces[8]); Console.WriteLine(bitboard.Pieces[9]); Console.WriteLine(bitboard.Pieces[10]); Console.WriteLine(bitboard.Pieces[11]); var save = new BoardWriter(); save.Write("err.board", new FriendlyBoard(bitboard)); // throw new PieceTypeNotFoundException(); }
/// <summary> /// Calculates Zobrist hash for pieces. /// </summary> /// <param name="hash">The current hash.</param> /// <param name="pieces">The array of pieces.</param> /// <returns>The updated Zobrist hash.</returns> private static ulong CalculatePieces(ulong hash, ulong[] pieces) { for (var colorIndex = 0; colorIndex < 2; colorIndex++) { var color = (Color)colorIndex; for (var pieceIndex = 0; pieceIndex < 6; pieceIndex++) { var piece = (PieceType)pieceIndex; var piecesArray = pieces[FastArray.GetPieceIndex(color, piece)]; while (piecesArray != 0) { var pieceLSB = BitOperations.GetLSB(piecesArray); piecesArray = BitOperations.PopLSB(piecesArray); var fieldIndex = BitOperations.GetBitIndex(pieceLSB); hash ^= ZobristContainer.Pieces[FastArray.GetZobristPieceIndex(color, piece, fieldIndex)]; } } } return(hash); }
/// <summary> /// Checks if king is on initial position and can be a part of castling. /// </summary> /// <param name="kingBitboard">The bitboard with set bit at king position.</param> /// <param name="opt">The generator parameters.</param> /// <returns>True if king is on initial position, otherwise false.</returns> private static bool IsKingOnPosition(ulong kingBitboard, GeneratorParameters opt) { return((opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.King)] & kingBitboard) != 0); }
/// <summary> /// Checks if rook is on initial position and can be a part of castling. /// </summary> /// <param name="rookBitboard">The bitboard with set bit at rook position.</param> /// <param name="opt">The generator parameters.</param> /// <returns>True if rook is on initial position, otherwise false.</returns> private static bool IsRookOnPosition(ulong rookBitboard, GeneratorParameters opt) { return((opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Rook)] & rookBitboard) != 0); }