diff --git a/Chess-Challenge/src/Framework/Application/Helpers/Tester.cs b/Chess-Challenge/src/Framework/Application/Helpers/Tester.cs index eef4fee..600a81e 100644 --- a/Chess-Challenge/src/Framework/Application/Helpers/Tester.cs +++ b/Chess-Challenge/src/Framework/Application/Helpers/Tester.cs @@ -113,6 +113,17 @@ namespace ChessChallenge.Application Assert(boardAPI.GetKingSquare(false) == new Square(6, 7), "King square wrong"); Assert(boardAPI.GetPiece(new Square(4, 5)).IsPawn, "Wrong piece"); Assert(!boardAPI.GetPiece(new Square(4, 5)).IsWhite, "Wrong colour"); + + API.Move testMove = new("g5e6", boardAPI); + boardAPI.MakeMove(testMove); + Assert(boardAPI.GetPiece(new Square("g5")).IsNull, "Wrong piece"); + Assert(boardAPI.GetPiece(new Square("e6")).IsKnight, "Wrong piece"); + Assert(boardAPI.GetPiece(new Square("e6")).IsWhite, "Wrong piece col"); + boardAPI.UndoMove(testMove); + Assert(boardAPI.GetPiece(new Square("e6")).IsPawn, "Wrong piece"); + Assert(!boardAPI.GetPiece(new Square("e6")).IsWhite, "Wrong piece col"); + Assert(boardAPI.GetPiece(new Square("g5")).IsKnight, "Wrong piece"); + } static void DrawTest() @@ -151,6 +162,43 @@ namespace ChessChallenge.Application Assert(!boardAPI.IsDraw(), "Draw wrong"); boardAPI.MakeMove(new API.Move("c5d7", boardAPI)); Assert(boardAPI.IsDraw(), "Draw wrong"); + + string[] notInsufficient = + { + "3k4/4b3/8/8/8/3B4/1K6/8 w - - 0 1", + "3k4/3b4/8/8/8/4B3/1K6/8 w - - 0 1", + "3k4/3b4/8/8/8/2N5/1K6/8 w - - 0 1", + "3k4/3n4/8/8/8/2N5/1K6/8 w - - 0 1", + "8/4k3/8/8/8/2NN4/1K6/8 w - - 0 1", + "8/4k3/8/8/8/8/PK6/8 w - - 0 1", + "8/4k3/8/8/8/8/1K1R4/8 w - - 0 1", + "8/4k3/8/8/8/8/1KQ5/8 w - - 0 1" + }; + + string[] insufficient = + { + "3k4/8/8/8/8/8/1K6/8 w - - 0 1", + "3k4/8/8/8/8/2B5/1K6/8 w - - 0 1", + "3k4/8/8/8/8/8/1KN5/8 w - - 0 1", + "3k4/2b5/8/8/8/2B5/1K6/8 w - - 0 1", + "3k4/3b4/8/8/8/3B4/1K6/8 w - - 0 1" + }; + + foreach (string drawPos in insufficient) + { + boardAPI = API.Board.CreateBoardFromFEN(drawPos); + Assert(boardAPI.IsDraw(), "Draw wrong, position is insufficient mat"); + boardAPI = API.Board.CreateBoardFromFEN(FenUtility.FlipFen(drawPos)); + Assert(boardAPI.IsDraw(), "Draw wrong, position is insufficient mat"); + } + + foreach (string winnablePos in notInsufficient) + { + boardAPI = API.Board.CreateBoardFromFEN(winnablePos); + Assert(!boardAPI.IsDraw(), "Draw wrong, position is winnable"); + boardAPI = API.Board.CreateBoardFromFEN(FenUtility.FlipFen(winnablePos)); + Assert(!boardAPI.IsDraw(), "Draw wrong, position is winnable"); + } } static void MiscTest() diff --git a/Chess-Challenge/src/Framework/Chess/Board/Board.cs b/Chess-Challenge/src/Framework/Chess/Board/Board.cs index fa683f7..3d1daef 100644 --- a/Chess-Challenge/src/Framework/Chess/Board/Board.cs +++ b/Chess-Challenge/src/Framework/Chess/Board/Board.cs @@ -266,9 +266,12 @@ namespace ChessChallenge.Chess UpdateSliderBitboards(); // Pawn moves and captures reset the fifty move counter and clear 3-fold repetition history - if (!inSearch && (movedPieceType == PieceHelper.Pawn || capturedPieceType != PieceHelper.None)) + if (movedPieceType == PieceHelper.Pawn || capturedPieceType != PieceHelper.None) { - RepetitionPositionHistory.Clear(); + if (!inSearch) + { + RepetitionPositionHistory.Clear(); + } newFiftyMoveCounter = 0; } diff --git a/Chess-Challenge/src/Framework/Chess/Helpers/BoardHelper.cs b/Chess-Challenge/src/Framework/Chess/Helpers/BoardHelper.cs index 4457ca8..fa3444f 100644 --- a/Chess-Challenge/src/Framework/Chess/Helpers/BoardHelper.cs +++ b/Chess-Challenge/src/Framework/Chess/Helpers/BoardHelper.cs @@ -60,6 +60,11 @@ return (fileIndex + rankIndex) % 2 != 0; } + public static bool LightSquare(int squareIndex) + { + return LightSquare(FileIndex(squareIndex), RankIndex(squareIndex)); + } + public static string SquareNameFromCoordinate(int fileIndex, int rankIndex) { return fileNames[fileIndex] + "" + (rankIndex + 1); diff --git a/Chess-Challenge/src/Framework/Chess/Result/Arbiter.cs b/Chess-Challenge/src/Framework/Chess/Result/Arbiter.cs index d98cca6..c2cd01b 100644 --- a/Chess-Challenge/src/Framework/Chess/Result/Arbiter.cs +++ b/Chess-Challenge/src/Framework/Chess/Result/Arbiter.cs @@ -84,20 +84,22 @@ int numBlackKnights = board.knights[Board.BlackIndex].Count; int numWhiteMinors = numWhiteBishops + numWhiteKnights; int numBlackMinors = numBlackBishops + numBlackKnights; + int numMinors = numWhiteMinors + numBlackMinors; - // King v King - if (numWhiteMinors == 0 && numBlackMinors == 0) + // Lone kings or King vs King + single minor: is insuffient + if (numMinors <= 1) { return true; } - // Single minor piece vs lone king - if ((numWhiteMinors == 1 && numBlackMinors == 0) || (numBlackMinors == 1 && numWhiteMinors == 0)) + // Bishop vs bishop: is insufficient when bishops are same colour complex + if (numMinors == 2 && numWhiteBishops == 1 && numBlackBishops == 1) { - return true; + bool whiteBishopIsLightSquare = BoardHelper.LightSquare(board.bishops[Board.WhiteIndex][0]); + bool blackBishopIsLightSquare = BoardHelper.LightSquare(board.bishops[Board.BlackIndex][0]); + return whiteBishopIsLightSquare == blackBishopIsLightSquare; } - return false;