private string GetSANSourceString(Board preMoveBoard, Move move) { var src = BoardHelpers.GetPieceAtIndex(preMoveBoard.Occupancy, move.SourceIndex); Debug.Assert(src.HasValue); if (src == Piece.King) { return("K"); } if (src == Piece.Pawn) { var source = ""; //if the move was an En Passant or a capture, return the file letter if (move.MoveType == MoveType.EnPassant || move.SourceIndex.GetFile() != move.DestinationIndex.GetFile()) { source = move.SourceIndex.IndexToFileDisplay().ToString(); } return(source); } var strSrcPiece = src.Value.GetCharRepresentation().ToString().ToUpper(); var otherLikePieces = preMoveBoard.Occupancy.Occupancy(preMoveBoard.ActivePlayer, src); var duplicateAttackerIndexes = new List <ushort>(); foreach (var attackerIndex in otherLikePieces.GetSetBits()) { var legalMoves = Bitboard.Instance.GetLegalMoves(attackerIndex, preMoveBoard.Occupancy, preMoveBoard.EnPassantIndex, preMoveBoard.CastlingAvailability); var canPieceMoveToDestination = legalMoves.Any(x => x.DestinationIndex == move.DestinationIndex); if (canPieceMoveToDestination) { duplicateAttackerIndexes.Add(attackerIndex); } } if (duplicateAttackerIndexes.Count == 1) { return(strSrcPiece); } var duplicateFiles = duplicateAttackerIndexes.Select(x => x.GetFile()).GroupBy(x => x) .Any(x => x.Count() > 1); var duplicateRanks = duplicateAttackerIndexes.Select(x => x.GetRank()).GroupBy(x => x) .Any(x => x.Count() > 1); if (!duplicateFiles) { return(strSrcPiece + move.SourceIndex.IndexToFileDisplay()); } if (!duplicateRanks) { return(strSrcPiece + move.SourceIndex.IndexToRankDisplay()); } return(strSrcPiece + move.SourceIndex.ToSquareString()); }
private static IEnumerable <TestCaseData> SetupPathSquareValidation(Board board, Move castlingMove) { var totalOccupancy = board.Occupancy.Occupancy(); var enPassantSquare = board.EnPassantIndex; var inBetweenSquares = BoardHelpers.InBetween(castlingMove.SourceIndex, castlingMove.DestinationIndex) | castlingMove.DestinationValue; var inBetweenSquareArr = inBetweenSquares.GetSetBits().ToArray(); var permutations = MovingPieceService.GetAllPermutationsOfSetBits(inBetweenSquareArr, 0, 0) .Distinct() .ToList(); TestContext.WriteLine(permutations); TestContext.WriteLine("----------------------------------------"); foreach (var attackedSquaresValue in permutations) { var bb = new Mock <IBitboard>(); var attackedSquares = attackedSquaresValue.GetSetBits(); foreach (var squareBetween in inBetweenSquareArr) { var isAttacked = attackedSquares.Contains(squareBetween); SetupMock(board, squareBetween, totalOccupancy, enPassantSquare, bb, isAttacked); } var strBlockers = attackedSquares.Any() ? string.Join(", ", attackedSquares) : "[None]"; TestContext.WriteLine($"Returning test case for {attackedSquaresValue}"); var expectedReturnValue = attackedSquares.Any() ? MoveError.CastleThroughCheck : MoveError.NoneSet; yield return(new TestCaseData(bb, board, castlingMove) .SetName($"Indices Attacked: {strBlockers}") .Returns(expectedReturnValue)); } }
public static IEnumerable <TestCaseData> GetCastlingMoves(Color color, Move move) { const string emptyFenWhiteToMove = "4k3/8/8/8/8/8/8/4K3 w - - 0 1"; const string emptyFenBlackToMove = "4k3/8/8/8/8/8/8/4K3 b - - 0 1"; var rookInitialSquareIndex = MoveHelpers.GetRookMoveForCastleMove(move).SourceIndex; var between = BoardHelpers.InBetween(rookInitialSquareIndex, move.SourceIndex); var blockerPermutations = MovingPieceService.GetAllPermutationsOfSetBits(between.GetSetBits(), 0, 0) .Where(x => x != 0); var fen = color == Color.Black ? emptyFenBlackToMove : emptyFenWhiteToMove; var board = fenTextToBoard.Translate(fen); foreach (var permutation in blockerPermutations) { var editedBoard = (Board)board.Clone(); editedBoard.Occupancy[(int)color][(int)Piece.King] = permutation; var strBlockers = string.Join(", ", permutation.GetSetBits()); yield return(new TestCaseData(editedBoard, move) .SetName($"Blockers on indices {strBlockers}") .Returns(MoveError.CastleOccupancyBetween)); } yield return(new TestCaseData(board, move) .SetName("No Blockers") .Returns(MoveError.NoneSet)); }
public static void InBetween_ShouldReturnCorrectValue_GivenH8A1() { var expected = 0x40201008040200; var actual = BoardHelpers.InBetween(63, 0); Assert.AreEqual(expected, actual, "Should return correct value for h8-a1"); }
public static void InBetween_ShouldReturnCorrectValue_GivenA1H8() { var expected = 0x40201008040200; var actual = BoardHelpers.InBetween(0, 63); Assert.AreEqual(expected, actual, "Should return correct value for a1-h8"); }
public void GetCheckTypeTest(TestCase <BoardHelpers.CheckType, Board> testCase) { var occupancy = testCase.TestMethodInputValue.Occupancy; var color = testCase.TestMethodInputValue.ActivePlayer; var actual = BoardHelpers.GetCheckType(occupancy, color, out _); Assert.AreEqual(testCase.ExpectedValue, actual, testCase.ToString()); }
public void IsStalemateTest(TestCase <bool, Board> testCase) { var actual = BoardHelpers.IsStalemate(testCase.TestMethodInputValue.Occupancy, testCase.TestMethodInputValue.ActivePlayer, testCase.TestMethodInputValue.EnPassantIndex, testCase.TestMethodInputValue.CastlingAvailability); Assert.AreEqual(testCase.ExpectedValue, actual); }
public static void InBetween_ShouldReturnZero_GivenTwoNSOneAnother() { var expected = (ulong)0x00; var actual = BoardHelpers.InBetween(1, 9); Assert.AreEqual(expected, actual, "Should not be any squares between squares N+S of ona another (b1-b2)"); }
public static void InBetween_ShouldReturnZero_GivenTwoEWOneAnother() { var expected = (ulong)0x00; var actual = BoardHelpers.InBetween(3, 4); Assert.AreEqual(expected, actual, "Should not be any squares between squares E+W of one another (d1-e1)"); }
public void GetEnPassantIndexTest(TestCase <ushort?, Board> testCase) { var actual = BoardHelpers.GetEnPassantIndex(testCase.TestMethodInputValue, (IMove)testCase.AdditionalInputs.Single()); Assert.AreEqual(testCase.ExpectedValue, actual, testCase.ToString()); }
public void GetCastlingAvailabilityPostMoveTest(TestCase <CastlingAvailability, Board> testCase) { var occupancy = testCase.TestMethodInputValue.Occupancy; var currentCastlingAvailability = testCase.TestMethodInputValue.CastlingAvailability; var move = (Move)testCase.AdditionalInputs.Single(); var actual = BoardHelpers.GetCastlingAvailabilityPostMove(occupancy, move, currentCastlingAvailability); Assert.AreEqual(testCase.ExpectedValue, actual, testCase.ToString()); }
public static void GetCheckType_ShouldReturnSingleForSingleChecks(string fen, string description = "") { var board = FenReader.Translate(fen); var result = BoardHelpers.GetCheckType(board.Occupancy, board.ActivePlayer, out _); var message = GetCheckmateTypeDescription(fen, description, result); Console.WriteLine(message); Assert.AreEqual(BoardHelpers.CheckType.Single, result, message); }
public void InBetweenTest(string strFrom, string strTo, ulong expected) { var from = strFrom.ToBoardIndex(); var to = strTo.ToBoardIndex(); Assert.IsNotNull(from); Assert.IsNotNull(to); var actual = BoardHelpers.InBetween(from, to); Assert.AreEqual(expected, actual, $"{strFrom}->{strTo}"); }
public static void TestRankCompliment() { Assert.AreEqual(0, BoardHelpers.RankCompliment(7)); Assert.AreEqual(1, BoardHelpers.RankCompliment(6)); Assert.AreEqual(2, BoardHelpers.RankCompliment(5)); Assert.AreEqual(3, BoardHelpers.RankCompliment(4)); Assert.AreEqual(4, BoardHelpers.RankCompliment(3)); Assert.AreEqual(5, BoardHelpers.RankCompliment(2)); Assert.AreEqual(6, BoardHelpers.RankCompliment(1)); Assert.AreEqual(7, BoardHelpers.RankCompliment(0)); }
public IEnumerable <IMove> GetLegalMoves(ushort squareIndex, ulong[][] occupancy, ushort?enPassantIdx, CastlingAvailability castlingAvailability) { var pieceOfColor = occupancy.GetPieceOfColorAtIndex(squareIndex); if (pieceOfColor == null) { yield break; } var piece = pieceOfColor.Value.Piece; var color = pieceOfColor.Value.Color; var relevantOccupancy = occupancy.Occupancy(); if (piece == Piece.Pawn && enPassantIdx.HasValue) { var epValue = enPassantIdx.Value.GetBoardValueOfIndex(); relevantOccupancy |= epValue; } var pseudoLegalMoves = GetPseudoLegalMoves(squareIndex, piece, color, relevantOccupancy); var moves = new List <IMove>(); foreach (var destinationIndex in pseudoLegalMoves.GetSetBits()) { var moveType = BoardHelpers.GetMoveType(occupancy, squareIndex, destinationIndex, enPassantIdx); var move = MoveHelpers.GenerateMove(squareIndex, destinationIndex, moveType); moves.Add(move); } if (piece == Piece.King && IsKingSquare(squareIndex, color)) { moves.AddRange(GetPseudoLegalCastlingMoves(color, castlingAvailability)); } foreach (var move in moves) { var moveValidator = new MoveValidator( new Board(occupancy, 0, enPassantIdx, null, castlingAvailability, color, 0, true), move); var validationResult = moveValidator.Validate(); if (validationResult == MoveError.NoneSet) { yield return(move); } } }
public static void InBetween_ShouldReturnCorrectValue_GivenRandomPositions() { var expected = (ulong)0x00; var actual = BoardHelpers.InBetween(3, 8); Assert.AreEqual(expected, actual, $"Should not be any squares between {3.ToSquareString()}{8.ToSquareString()}"); expected = 0x200; actual = BoardHelpers.InBetween(16, 2); Assert.AreEqual(expected, actual, $"Did not return correct value for in between {16.ToSquareString()} - {2.ToSquareString()}"); expected = 0x2040800000000; actual = BoardHelpers.InBetween(28, 56); Assert.AreEqual(expected, actual, $"Did not return correct value for in between {28.ToSquareString()} - {56.ToSquareString()}"); }
public override string Translate(Move move, Board preMoveBoard, Board postMoveBoard) { string capture = "", promotionPiece = "", checkInfo = "", result = ""; if (move.MoveType == MoveType.Castle) { return(CastleToSan(move)); } var strSrcPiece = GetSANSourceString(preMoveBoard, move); if (postMoveBoard.PieceCaptured.HasValue) { capture = "x"; } if (move.MoveType == MoveType.Promotion) { promotionPiece = $"={PieceHelpers.GetCharFromPromotionPiece(move.PromotionPiece)}"; } if (BoardHelpers.IsColorInCheck(postMoveBoard.Occupancy, postMoveBoard.ActivePlayer)) { checkInfo = "+"; if (postMoveBoard.GameState == GameState.Checkmate) { checkInfo = "#"; } } //Get piece representation var san = $"{strSrcPiece}{capture}{move.DestinationIndex.ToSquareString()}{promotionPiece}{checkInfo} {result}" .Trim(); return(san); }
public void ValidateIndexTest() { Assert.Throws <ArgumentException>(delegate { BoardHelpers.ValidateIndex(64); }); Assert.DoesNotThrow(delegate { BoardHelpers.ValidateIndex(63); }); Assert.DoesNotThrow(delegate { BoardHelpers.ValidateIndex(0); }); }
public void GetPieceAtIndexTest(TestCase <Piece?, ushort> testCase) { var actual = BoardHelpers.GetPieceAtIndex(BoardHelpers.InitialBoard, testCase.TestMethodInputValue); Assert.AreEqual(testCase.ExpectedValue, actual, testCase.Description); }
public MoveType GetMoveTypeTest(Board board, ushort from, ushort to, ushort?epIndex) { return(BoardHelpers.GetMoveType(board.Occupancy, (ushort)@from, (ushort)to, (ushort?)epIndex)); }
public void IsCheckmateTest(TestCase <bool, Board> testCase) { var actual = BoardHelpers.IsCheckmate(testCase.TestMethodInputValue); Assert.AreEqual(testCase.ExpectedValue, actual, testCase.ToString()); }
public static void Main(string[] args) { // Create the board var board = BoardFactory.CreateBoard(); BasicPlayer player1 = new BasicPlayer(board, Player.PlayerOne); board.AddPlayer(player1); BasicPlayer player2 = new BasicPlayer(board, Player.PlayerTwo); board.AddPlayer(player2); // Loop until the game is over while (board.GameState != GameState.Ended) { // Render the board in the console PrintBoardToConsole(board); // Fetch the current players turn Console.Write(board.PlayerTurn.ToFriendlyString() + " enter your move: "); var moveString = Console.ReadLine(); // Ensure the input is in the correct format (xFrom,yFrom,xTo,yTo) - no commas and must be in the correct chess notation e.g. a1a3 if (!BoardHelpers.ValidMoveRepresentation(moveString)) { Console.WriteLine("Invalid string, please enter it again."); continue; } // Fetch the available moves for the player var validMoves = new HashSet <BoardPieceMove>(); ValidMovesCalc.GetValidMovesForPlayer(board, board.PlayerTurn, validMoves); // Create an instance of the move var from = BoardHelpers.ConvertStringRepIntoPos(moveString.Substring(0, 2)); var to = BoardHelpers.ConvertStringRepIntoPos(moveString.Substring(2, 2)); var move = new BoardPieceMove(from, to); // Make sure the move is legal if (!validMoves.Contains(move)) { Console.WriteLine("Invalid move, please enter it again."); continue; } // Apply the move if (board.PlayerTurn == Player.PlayerOne) { player1.ApplyMove(move); } else { player2.ApplyMove(move); } } PrintBoardToConsole(board); Console.WriteLine(board.PlayerTurn.ToFriendlyString() + " wins!"); Console.ReadLine(); }