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 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); } } }
private void GenerateQuietMoves(MoveList moves) { var currentSide = _position.State.SideToMove; var up = currentSide == PlayerExtensions.White ? EDirection.North : EDirection.South; var notOccupied = ~_position.Pieces(); var pushed = (_position.Pieces(EPieceType.Pawn, currentSide) & ~currentSide.Rank7()).Shift(up) & notOccupied; AddPawnMoves(moves, pushed, currentSide.PawnPushDistance(), EMoveType.Quiet); pushed &= currentSide.Rank3(); AddPawnMoves(moves, pushed.Shift(up) & notOccupied, currentSide.PawnDoublePushDistance(), EMoveType.Doublepush); AddMoves(moves, notOccupied); if (_position.InCheck) { return; } for (var castleType = ECastleling.Short; castleType < ECastleling.CastleNb; castleType++) { if (_position.CanCastle(castleType)) { AddCastleMove(moves, _position.GetKingCastleFrom(currentSide, castleType), castleType.GetKingCastleTo(currentSide)); } } }
public void GenerateMoves(bool force = false) { // Align current structure to position. Reset(MoveExtensions.EmptyMove); // this is only preparation for true engine integration (not used yet) //if (Flags.HasFlagFast(Emgf.Stages)) // return; if (Table.TryGetValue(_position.State.Key, out var moves) && !force) { Moves = moves; } else { moves = new MoveList(); // relax the gc while generating moves. var old = GCSettings.LatencyMode; GCSettings.LatencyMode = GCLatencyMode.LowLatency; GenerateCapturesAndPromotions(moves); GenerateQuietMoves(moves); Table.TryAdd(_position.State.Key, moves); Moves = moves; GCSettings.LatencyMode = old; } }
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); }
private void AddMoves(MoveList moves, Piece piece, Square from, BitBoard attacks) { var target = _position.Pieces(~_position.State.SideToMove) & attacks; foreach (var to in target) { AddMove(moves, piece, from, to, EPieces.NoPiece, EMoveType.Capture); } target = ~_position.Pieces() & attacks; foreach (var to in target) { AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece); } }
/// <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 void AddMoves(MoveList moves, BitBoard targetSquares) { var c = _position.State.SideToMove; var occupied = _position.Pieces(); for (var pt = EPieceType.King; pt >= EPieceType.Knight; --pt) { var pc = pt.MakePiece(c); var pieces = _position.Pieces(pc); foreach (var from in pieces) { AddMoves(moves, pc, from, from.GetAttacks(pt, occupied) & targetSquares); } } }
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); } } }
/// <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); } } }
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); } }
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 void AddPawnMoves(MoveList moves, BitBoard targetSquares, Direction direction, EMoveType type) { if (targetSquares.Empty()) { return; } var piece = EPieceType.Pawn.MakePiece(_position.State.SideToMove); foreach (var squareTo in targetSquares) { var squareFrom = squareTo - direction; if (!squareTo.IsPromotionRank()) { AddMove(moves, piece, squareFrom, squareTo, PieceExtensions.EmptyPiece, type); } else { if (Flags.HasFlagFast(Emgf.Queenpromotion)) { AddMove(moves, piece, squareFrom, squareTo, EPieceType.Queen.MakePiece(_position.State.SideToMove), type | EMoveType.Promotion); } else { for (var promotedPiece = EPieceType.Queen; promotedPiece >= EPieceType.Knight; promotedPiece--) { AddMove(moves, piece, squareFrom, squareTo, promotedPiece.MakePiece(_position.State.SideToMove), type | EMoveType.Promotion); } } } } }
private void GenerateCapturesAndPromotions(MoveList moves) { var currentSide = _position.State.SideToMove; var them = ~currentSide; var occupiedByThem = _position.OccupiedBySide[them.Side]; var(northEast, northWest) = currentSide == PlayerExtensions.White ? (EDirection.NorthEast, EDirection.NorthWest) : (EDirection.SouthEast, EDirection.SouthWest); AddMoves(moves, occupiedByThem); var pawns = _position.Pieces(EPieceType.Pawn, currentSide); AddPawnMoves(moves, currentSide.PawnPush(pawns & currentSide.Rank7()) & ~_position.Pieces(), currentSide.PawnPushDistance(), EMoveType.Quiet); AddPawnMoves(moves, pawns.Shift(northEast) & occupiedByThem, currentSide.PawnWestAttackDistance(), EMoveType.Capture); AddPawnMoves(moves, pawns.Shift(northWest) & occupiedByThem, currentSide.PawnEastAttackDistance(), EMoveType.Capture); if (_position.State.EnPassantSquare == ESquare.none) { return; } AddPawnMoves(moves, pawns.Shift(northEast) & _position.State.EnPassantSquare, currentSide.PawnWestAttackDistance(), EMoveType.Epcapture); AddPawnMoves(moves, pawns.Shift(northWest) & _position.State.EnPassantSquare, currentSide.PawnEastAttackDistance(), EMoveType.Epcapture); }
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 void AddCastleMove(MoveList moves, Square from, Square to) => AddMove(moves, EPieceType.King.MakePiece(_position.State.SideToMove), from, to, PieceExtensions.EmptyPiece, EMoveType.Castle);