Beispiel #1
0
        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());
        }
Beispiel #2
0
        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");
            }
Beispiel #6
0
        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());
        }
Beispiel #7
0
        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)");
            }
Beispiel #10
0
        public void GetEnPassantIndexTest(TestCase <ushort?, Board> testCase)
        {
            var actual =
                BoardHelpers.GetEnPassantIndex(testCase.TestMethodInputValue,
                                               (IMove)testCase.AdditionalInputs.Single());

            Assert.AreEqual(testCase.ExpectedValue, actual, testCase.ToString());
        }
Beispiel #11
0
        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);
        }
Beispiel #13
0
        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));
 }
Beispiel #15
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()}");
            }
Beispiel #17
0
        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);
        }
Beispiel #18
0
 public void ValidateIndexTest()
 {
     Assert.Throws <ArgumentException>(delegate { BoardHelpers.ValidateIndex(64); });
     Assert.DoesNotThrow(delegate { BoardHelpers.ValidateIndex(63); });
     Assert.DoesNotThrow(delegate { BoardHelpers.ValidateIndex(0); });
 }
Beispiel #19
0
        public void GetPieceAtIndexTest(TestCase <Piece?, ushort> testCase)
        {
            var actual = BoardHelpers.GetPieceAtIndex(BoardHelpers.InitialBoard, testCase.TestMethodInputValue);

            Assert.AreEqual(testCase.ExpectedValue, actual, testCase.Description);
        }
Beispiel #20
0
 public MoveType GetMoveTypeTest(Board board, ushort from, ushort to, ushort?epIndex)
 {
     return(BoardHelpers.GetMoveType(board.Occupancy, (ushort)@from,
                                     (ushort)to, (ushort?)epIndex));
 }
Beispiel #21
0
        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();
        }