private static void GenerateKnightMoves(GameState gameState, MoveGenerationMode generationMode, ulong freeSquares, ulong knightBoard, uint movingPiece, ulong[] attackSquares, ulong attackedBoard, int ply) { var move = 0U.SetMovingPiece(movingPiece); while (knightBoard > 0) { uint fromSquare = knightBoard.GetFirstPieceFromBitBoard(); move = move.SetFromMove(fromSquare); var knightMoves = 0UL; if (generationMode != MoveGenerationMode.CaptureMovesOnly) { knightMoves = attackSquares[fromSquare] & freeSquares; } if (generationMode == MoveGenerationMode.CaptureMovesOnly || generationMode == MoveGenerationMode.All) { knightMoves |= attackSquares[fromSquare] & attackedBoard; } while (knightMoves > 0) { uint toSquare = knightMoves.GetFirstPieceFromBitBoard(); move = move.SetToMove(toSquare); move = move.SetCapturedPiece(gameState.BoardArray[toSquare]); gameState.Moves[ply].Add(move); knightMoves ^= MoveUtility.BitStates[toSquare]; } knightBoard ^= MoveUtility.BitStates[fromSquare]; } }
private static void GenerateBishopMoves(GameState gameState, MoveData moveData, MoveGenerationMode generationMode, ulong freeSquares, ulong bishopBoard, uint movingPiece, ulong attackedBoard, int ply) { var move = 0U.SetMovingPiece(movingPiece); while (bishopBoard > 0) { uint fromSquare = bishopBoard.GetFirstPieceFromBitBoard(); move = move.SetFromMove(fromSquare); var bishopMoves = 0UL; if (generationMode != MoveGenerationMode.CaptureMovesOnly) { bishopMoves = moveData.GetBishopMoves(fromSquare, gameState.AllPieces, freeSquares) & freeSquares; } if (generationMode == MoveGenerationMode.CaptureMovesOnly || generationMode == MoveGenerationMode.All) { bishopMoves |= moveData.GetBishopMoves(fromSquare, gameState.AllPieces, attackedBoard) & attackedBoard; } while (bishopMoves > 0) { uint toSquare = bishopMoves.GetFirstPieceFromBitBoard(); move = move.SetToMove(toSquare); move = move.SetCapturedPiece(gameState.BoardArray[toSquare]); gameState.Moves[ply].Add(move); bishopMoves ^= MoveUtility.BitStates[toSquare]; } bishopBoard ^= MoveUtility.BitStates[fromSquare]; } }
public void Does_Not_Generate_Invalid_Black_Rook_Captures_Against_Own_Pieces(MoveGenerationMode mode) { var gameState = new GameState("8/8/8/3p4/2prp3/3p4/8/8 b - - 0 1", _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var testMoves = gameState.Moves[1].Where(x => x.GetMovingPiece() == MoveUtility.BlackRook); Assert.That(testMoves, Is.Empty); }
public void Does_Not_Generate_Invalid_White_Pawn_Captures(MoveGenerationMode mode) { var gameState = new GameState("8/8/RRRRRRRR/PPPPPPPP/8/8/8/8 w - - 0 1", _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var moves = gameState.Moves[1].Where(x => x.GetMovingPiece() == MoveUtility.WhitePawn); Assert.That(moves, Is.Empty); }
public void Does_Not_Generate_Invalid_White_King_Captures_Against_Own_Pieces(MoveGenerationMode mode) { var gameState = new GameState("8/8/8/2PPP3/2PKP3/2PPP3/8/8 w - - 0 1", _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var testMoves = gameState.Moves[1].Where(x => x.GetMovingPiece() == MoveUtility.WhiteRook); Assert.That(testMoves, Is.Empty); }
/// <summary> /// Generates the pseudo legal moves from a given gamestate /// </summary> /// <param name="gameState">The gamestate to generate from</param> /// <param name="generationMode">The generation move <see cref="MoveGenerationMode"/></param> /// <param name="ply">The ply to generate moves for</param> /// <param name="moveData">The move data</param> internal static void GenerateMoves(this GameState gameState, MoveGenerationMode generationMode, int ply, MoveData moveData) { var freeSquares = ~gameState.AllPieces; if (!gameState.Moves.ContainsKey(ply)) { gameState.Moves.Add(ply, new List <uint>(218)); } else { gameState.Moves[ply].Clear(); } if (gameState.WhiteToMove) { GenerateWhitePawnMoves(gameState, moveData, generationMode, freeSquares, ply); GenerateKnightMoves(gameState, generationMode, freeSquares, gameState.WhiteKnights, MoveUtility.WhiteKnight, moveData.KnightAttacks, gameState.BlackPieces, ply); GenerateRookMoves(gameState, moveData, generationMode, freeSquares, gameState.WhiteRooks, MoveUtility.WhiteRook, gameState.BlackPieces, ply); GenerateBishopMoves(gameState, moveData, generationMode, freeSquares, gameState.WhiteBishops, MoveUtility.WhiteBishop, gameState.BlackPieces, ply); GenerateQueenMoves(gameState, moveData, generationMode, freeSquares, gameState.WhiteQueens, MoveUtility.WhiteQueen, gameState.BlackPieces, ply); GenerateKingMoves(gameState, moveData, generationMode, freeSquares, gameState.WhiteKing, MoveUtility.WhiteKing, moveData.KingAttacks, gameState.BlackPieces, gameState.CurrentWhiteCastleStatus, WhiteCastleOOMask, WhiteCastleAttackOOMask, WhiteCastleOOOMask, WhiteCastleAttackOOOMask, moveData.WhiteCastleOOMove, moveData.WhiteCastleOOOMove, true, ply); } else { GenerateBlackPawnMoves(gameState, moveData, generationMode, freeSquares, ply); GenerateKnightMoves(gameState, generationMode, freeSquares, gameState.BlackKnights, MoveUtility.BlackKnight, moveData.KnightAttacks, gameState.WhitePieces, ply); GenerateRookMoves(gameState, moveData, generationMode, freeSquares, gameState.BlackRooks, MoveUtility.BlackRook, gameState.WhitePieces, ply); GenerateBishopMoves(gameState, moveData, generationMode, freeSquares, gameState.BlackBishops, MoveUtility.BlackBishop, gameState.WhitePieces, ply); GenerateQueenMoves(gameState, moveData, generationMode, freeSquares, gameState.BlackQueens, MoveUtility.BlackQueen, gameState.WhitePieces, ply); GenerateKingMoves(gameState, moveData, generationMode, freeSquares, gameState.BlackKing, MoveUtility.BlackKing, moveData.KingAttacks, gameState.WhitePieces, gameState.CurrentBlackCastleStatus, BlackCastleOOMask, BlackCastleAttackOOMask, BlackCastleOOOMask, BlackCastleAttackOOOMask, moveData.BlackCastleOOMove, moveData.BlackCastleOOOMove, false, ply); } }
private static void GenerateBlackPawnMoves(GameState gameState, MoveData moveData, MoveGenerationMode generationMode, ulong freeSquares, int ply) { var pawnBoard = gameState.BlackPawns; var move = 0U.SetMovingPiece(MoveUtility.BlackPawn); while (pawnBoard > 0) { uint fromSquare = pawnBoard.GetFirstPieceFromBitBoard(); move = move.SetFromMove(fromSquare); var pawnMoves = 0UL; //Single and double pawn pushes, no promotions if (generationMode != MoveGenerationMode.CaptureMovesOnly) { //Normal Moves pawnMoves |= moveData.BlackPawnMoves[fromSquare] & freeSquares; //Double Moves if (MoveUtility.Ranks[fromSquare] == 7 && pawnMoves > 0) { pawnMoves |= moveData.BlackPawnDoubleMoves[fromSquare] & freeSquares; } } //Standard Captures. if (generationMode == MoveGenerationMode.CaptureMovesOnly || generationMode == MoveGenerationMode.All) { //Captures pawnMoves |= moveData.BlackPawnAttacks[fromSquare] & gameState.WhitePieces; if (gameState.EnpassantTargetSquare > 0) { if ((moveData.BlackPawnAttacks[fromSquare] & MoveUtility.BitStates[gameState.EnpassantTargetSquare]) > 0) { if ((gameState.WhitePawns & MoveUtility.BitStates[gameState.EnpassantTargetSquare + 8]) > 0) { move = move.SetPromotionPiece(MoveUtility.BlackPawn); move = move.SetCapturedPiece(MoveUtility.WhitePawn); move = move.SetToMove(gameState.EnpassantTargetSquare); gameState.Moves[ply].Add(move); move = move.SetPromotionPiece(MoveUtility.EmptyPiece); } } } } while (pawnMoves > 0) { uint toSquare = pawnMoves.GetFirstPieceFromBitBoard(); move = move.SetToMove(toSquare); move = move.SetCapturedPiece(gameState.BoardArray[toSquare]); if (MoveUtility.Ranks[toSquare] == 1) { //Knights and Queens are good enough for now for all generation types move = move.SetPromotionPiece(MoveUtility.BlackQueen); gameState.Moves[ply].Add(move); move = move.SetPromotionPiece(MoveUtility.BlackKnight); gameState.Moves[ply].Add(move); //A queen is always preferable to a rook and bishop, so no need to generate these, unless we have a reason to generate all pseudo legal moves if (generationMode == MoveGenerationMode.All) { move = move.SetPromotionPiece(MoveUtility.BlackBishop); gameState.Moves[ply].Add(move); move = move.SetPromotionPiece(MoveUtility.BlackRook); gameState.Moves[ply].Add(move); } //Reset it back to empty so it doesn't screw up the next piece! move = move.SetPromotionPiece(MoveUtility.EmptyPiece); } else { gameState.Moves[ply].Add(move); } //Remove the bit we just processed from the board pawnMoves ^= MoveUtility.BitStates[toSquare]; } pawnBoard ^= MoveUtility.BitStates[fromSquare]; } }
private static void GenerateKingMoves(GameState gameState, MoveData moveData, MoveGenerationMode generationMode, ulong freeSquares, ulong kingBoard, uint movingPiece, ulong[] attackSquares, ulong attackedBoard, int castleStatus, ulong castleMaskOO, ulong castleAttackMaskOO, ulong castleMaskOOO, ulong castleAttackMaskOOO, uint castleOOMove, uint castleOOOMove, bool whitetoMove, int ply) { var move = 0U.SetMovingPiece(movingPiece); while (kingBoard > 0) { var fromSquare = kingBoard.GetFirstPieceFromBitBoard(); move = move.SetFromMove(fromSquare); var kingMoves = 0UL; if (generationMode != MoveGenerationMode.CaptureMovesOnly) { kingMoves = attackSquares[fromSquare] & freeSquares; if (castleStatus.CanCastleOO()) { if ((castleMaskOO & gameState.AllPieces) == 0) { if (!IsBitBoardAttacked(gameState, moveData, castleAttackMaskOO, !whitetoMove)) { gameState.Moves[ply].Add(castleOOMove); } } } if (castleStatus.CanCastleOOO()) { if ((castleMaskOOO & gameState.AllPieces) == 0) { if (!IsBitBoardAttacked(gameState, moveData, castleAttackMaskOOO, !whitetoMove)) { gameState.Moves[ply].Add(castleOOOMove); } } } } if (generationMode == MoveGenerationMode.CaptureMovesOnly || generationMode == MoveGenerationMode.All) { kingMoves |= attackSquares[fromSquare] & attackedBoard; } while (kingMoves > 0) { uint toSquare = kingMoves.GetFirstPieceFromBitBoard(); move = move.SetToMove(toSquare); move = move.SetCapturedPiece(gameState.BoardArray[toSquare]); gameState.Moves[ply].Add(move); kingMoves ^= MoveUtility.BitStates[toSquare]; } kingBoard ^= MoveUtility.BitStates[fromSquare]; } }
public void Generates_Valid_White_Rook_Captures_When_Not_QuietMovesOnly(uint fromMove, uint toMove, MoveGenerationMode mode) { var gameState = new GameState("8/8/3p4/8/1p1R1p2/8/3p4/8 w - - 0 1", _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var move = gameState.Moves[1].First(x => x.GetFromMove() == fromMove && x.GetToMove() == toMove); var capturedPiece = move.GetCapturedPiece(); var movingPiece = move.GetMovingPiece(); var promotedPiece = move.GetPromotedPiece(); Assert.That(movingPiece, Is.EqualTo(MoveUtility.WhiteRook), "Moving Piece"); Assert.That(capturedPiece, Is.EqualTo(MoveUtility.BlackPawn), "Captured Piece"); Assert.That(promotedPiece, Is.EqualTo(MoveUtility.EmptyPiece), "Promoted Piece"); }
public void Generates_Valid_Black_Pawn_EnPassant_Moves_When_Not_QuietMovesOnly(uint fromMove, uint toMove, MoveGenerationMode mode) { var gameState = new GameState(fromMove % 2 == 0 ? "8/8/8/8/pPpPpPpP/8/8/8 b - - 0 1" : "8/8/8/8/PpPpPpPp/8/8/8 b - - 0 1", _zobristHash) { EnpassantTargetSquare = toMove }; gameState.GenerateMoves(MoveGenerationMode.All, 1, _moveData); var move = gameState.Moves[1].First(x => x.GetFromMove() == fromMove && x.GetToMove() == toMove); var capturedPiece = move.GetCapturedPiece(); var movingPiece = move.GetMovingPiece(); var promotedPiece = move.GetPromotedPiece(); Assert.That(movingPiece, Is.EqualTo(MoveUtility.BlackPawn), "Moving Piece"); Assert.That(capturedPiece, Is.EqualTo(MoveUtility.WhitePawn), "Captured Piece"); Assert.That(promotedPiece, Is.EqualTo(MoveUtility.BlackPawn), "En Passant Piece"); }
public void Generates_Valid_WhiteDoublePawn_Moves_When_Not_CapturesOnly(uint fromMove, uint toMove, MoveGenerationMode mode) { var gameState = new GameState("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var move = gameState.Moves[1].First(x => x.GetFromMove() == fromMove && x.GetToMove() == toMove); var capturedPiece = move.GetCapturedPiece(); var promotedPiece = move.GetPromotedPiece(); var movingPiece = move.GetMovingPiece(); Assert.That(movingPiece, Is.EqualTo(MoveUtility.WhitePawn), "Moving Piece"); Assert.That(capturedPiece, Is.EqualTo(MoveUtility.EmptyPiece), "Captured Piece"); Assert.That(promotedPiece, Is.EqualTo(MoveUtility.EmptyPiece), "Promoted Piece"); }
public void Generates_Valid_Black_King_Castling_When_Not_Capture_Only(uint toMove, string fen, MoveGenerationMode mode) { var gameState = new GameState(fen, _zobristHash); gameState.GenerateMoves(mode, 1, _moveData); var move = gameState.Moves[1].First(x => x.GetFromMove() == 60U && x.GetToMove() == toMove); var capturedPiece = move.GetCapturedPiece(); var movingPiece = move.GetMovingPiece(); var promotedPiece = move.GetPromotedPiece(); Assert.That(movingPiece, Is.EqualTo(MoveUtility.BlackKing), "Moving Piece"); Assert.That(capturedPiece, Is.EqualTo(MoveUtility.EmptyPiece), "Captured Piece"); Assert.That(promotedPiece, Is.EqualTo(MoveUtility.BlackKing), "Promoted Piece"); }