private static void GenerateQuietMoves(this IPosition pos, MoveList moves, Emgf flags) { var currentSide = pos.State.SideToMove; var up = currentSide == PlayerExtensions.White ? EDirection.North : EDirection.South; var notOccupied = ~pos.Pieces(); var pushed = (pos.Pieces(EPieceType.Pawn, currentSide) & ~currentSide.Rank7()).Shift(up) & notOccupied; pos.AddPawnMoves(moves, pushed, currentSide.PawnPushDistance(), EMoveType.Quiet, flags); pushed &= currentSide.Rank3(); pos.AddPawnMoves(moves, pushed.Shift(up) & notOccupied, currentSide.PawnDoublePushDistance(), EMoveType.Doublepush, flags); pos.AddMoves(moves, notOccupied, flags); if (pos.InCheck) { return; } for (var castleType = ECastleling.Short; castleType < ECastleling.CastleNb; castleType++) { if (pos.CanCastle(castleType)) { pos.AddCastleMove(moves, pos.GetKingCastleFrom(currentSide, castleType), castleType.GetKingCastleTo(currentSide), flags); } } }
public static MoveList GenerateMoves(this IPosition pos, Emgf flags = Emgf.Legalmoves, bool useCache = true, bool force = false) { pos.State.Pinned = flags.HasFlagFast(Emgf.Legalmoves) ? pos.GetPinnedPieces(pos.GetPieceSquare(EPieceType.King, pos.State.SideToMove), pos.State.SideToMove) : BitBoards.EmptyBitBoard; var moves = new MoveList(); pos.GenerateCapturesAndPromotions(moves, flags); pos.GenerateQuietMoves(moves, flags); return(moves); }
public static bool HasFlagFast(this Emgf value, Emgf flag) => (value & flag) != 0;
private static void GenerateCapturesAndPromotions(this IPosition pos, MoveList moves, Emgf flags) { var currentSide = pos.State.SideToMove; var them = ~currentSide; var occupiedByThem = pos.OccupiedBySide[them.Side]; var(northEast, northWest) = currentSide.GetPawnAttackDirections(); var pawns = pos.Pieces(EPieceType.Pawn, currentSide); pos.AddPawnMoves(moves, currentSide.PawnPush(pawns & currentSide.Rank7()) & ~pos.Pieces(), currentSide.PawnPushDistance(), EMoveType.Quiet, flags); pos.AddPawnMoves(moves, pawns.Shift(northEast) & occupiedByThem, currentSide.PawnWestAttackDistance(), EMoveType.Capture, flags); pos.AddPawnMoves(moves, pawns.Shift(northWest) & occupiedByThem, currentSide.PawnEastAttackDistance(), EMoveType.Capture, flags); if (pos.State.EnPassantSquare != ESquare.none) { pos.AddPawnMoves(moves, pawns.Shift(northEast) & pos.State.EnPassantSquare, currentSide.PawnWestAttackDistance(), EMoveType.Epcapture, flags); pos.AddPawnMoves(moves, pawns.Shift(northWest) & pos.State.EnPassantSquare, currentSide.PawnEastAttackDistance(), EMoveType.Epcapture, flags); } pos.AddMoves(moves, occupiedByThem, flags); }
private static void AddMove(this IPosition pos, MoveList moves, Piece piece, Square from, Square to, Piece promoted, Emgf flags, EMoveType type = EMoveType.Quiet) { Move move; if (type.HasFlagFast(EMoveType.Capture)) { move = new Move(piece, pos.GetPiece(to), from, to, type, promoted); } else if (type.HasFlagFast(EMoveType.Epcapture)) { move = new Move(piece, EPieceType.Pawn.MakePiece(~pos.State.SideToMove), from, to, type, promoted); } else { move = new Move(piece, from, to, type, promoted); } // check if move is actual a legal move if the flag is enabled if (flags.HasFlagFast(Emgf.Legalmoves) && !pos.IsLegal(move, piece, from, type)) { return; } moves.Add(move); }
private static void AddCastleMove(this IPosition pos, MoveList moves, Square from, Square to, Emgf flags) => pos.AddMove(moves, EPieceType.King.MakePiece(pos.State.SideToMove), from, to, PieceExtensions.EmptyPiece, flags, EMoveType.Castle);
private static void AddPawnMoves(this IPosition pos, MoveList moves, BitBoard targetSquares, Direction direction, EMoveType type, Emgf flags) { if (targetSquares.Empty()) { return; } var stm = pos.State.SideToMove; var piece = EPieceType.Pawn.MakePiece(stm); var promotionRank = stm.PromotionRank(); var promotionSquares = targetSquares & promotionRank; var nonPromotionSquares = targetSquares & ~promotionRank; while (nonPromotionSquares) { var to = nonPromotionSquares.Lsb(); var from = to - direction; pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags, type); BitBoards.ResetLsb(ref nonPromotionSquares); } type |= EMoveType.Promotion; if (flags.HasFlagFast(Emgf.Queenpromotion)) { var sqTo = promotionSquares.Lsb(); var sqFrom = sqTo - direction; pos.AddMove(moves, piece, sqFrom, sqTo, EPieceType.Queen.MakePiece(stm), flags, type); BitBoards.ResetLsb(ref promotionSquares); } else { while (promotionSquares) { var sqTo = promotionSquares.Lsb(); var sqFrom = sqTo - direction; for (var promotedPiece = EPieceType.Queen; promotedPiece >= EPieceType.Knight; promotedPiece--) { pos.AddMove(moves, piece, sqFrom, sqTo, promotedPiece.MakePiece(stm), flags, type); } BitBoards.ResetLsb(ref promotionSquares); } } }
private static void AddMoves(this IPosition pos, MoveList moves, Piece piece, Square from, BitBoard attacks, Emgf flags) { var target = pos.Pieces(~pos.State.SideToMove) & attacks; while (target) { var to = target.Lsb(); pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags, EMoveType.Capture); BitBoards.ResetLsb(ref target); } target = ~pos.Pieces() & attacks; while (target) { var to = target.Lsb(); pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags); BitBoards.ResetLsb(ref target); } }
/// <summary> /// Iterates through the piece types and generates moves based on their attacks. /// It does not contain any checks for moves that are invalid, as the leaf methods /// contains implicit denial of move generation if the target bitboard is empty. /// </summary> /// <param name="moves">The move list to add potential moves to.</param> /// <param name="targetSquares">The target squares to move to</param> private static void AddMoves(this IPosition pos, MoveList moves, BitBoard targetSquares, Emgf flags) { var c = pos.State.SideToMove; var occupied = pos.Pieces(); for (var pt = EPieceType.Knight; pt <= EPieceType.King; ++pt) { var pc = pt.MakePiece(c); var pieces = pos.Pieces(pc); while (pieces) { var from = pieces.Lsb(); pos.AddMoves(moves, pc, from, from.GetAttacks(pt, occupied) & targetSquares, flags); BitBoards.ResetLsb(ref pieces); } } }