#include "ChessArbiter.hpp" #include using namespace chessarbiter; TEST_CASE("Setup/GetBoard", "[chessarbiter/Setup/GetBoard]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetBoard() == "rnbqkbnr" "pppppppp" " " " " " " " " "PPPPPPPP" "RNBQKBNR"); a.Setup("RnbqkbnR/pppppppp/8/8/8/8/PPPPPPPP/rNBQKBNr w KQkq - 0 1"); CHECK(a.GetBoard() == "RnbqkbnR" "pppppppp" " " " " " " " " "PPPPPPPP" "rNBQKBNr"); } TEST_CASE("GetMaterialScore", "[chessarbiter/GetMaterialScore]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 0); // White better a.Setup("1nbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 5); a.Setup("r1bqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 3); a.Setup("rnbqkbnr/1ppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 1); a.Setup("rnb1kbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 9); a.Setup("rnbqk1nr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 3); a.Setup("rnbq1bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 0); // Black better a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/1NBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == -5); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKB1R w KQkq - 0 1"); CHECK(a.GetMaterialScore() == -3); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPP1/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == -1); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNB1KBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == -9); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RN1QKBNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == -3); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQ1BNR w KQkq - 0 1"); CHECK(a.GetMaterialScore() == 0); } TEST_CASE("GetCaptures", "[board/GetCaptures]") { ChessArbiter a; // White captures a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == ""); a.Setup("rnbqkbnr/8/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "pppppppp"); a.Setup("1nbqkbn1/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "rr"); a.Setup("r1bqkb1r/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "nn"); a.Setup("rnbqk1nr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "b"); a.Setup("rnb1kbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "q"); a.Setup("rnbq1bnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "k"); // :D // Black captures a.Setup("rnbqkbnr/pppppppp/8/8/8/8/8/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "PPPPPPPP"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/1NBQKBN1 w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "RR"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/R1BQKB1R w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "NN"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNbQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "B"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNB1KBNR w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "Q"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQ1BNR w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "K"); // :D // Just because we know the order of the implementation a.Setup("11bqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.GetCaptures(false) == "rn"); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKB11 w KQkq - 0 1"); CHECK(a.GetCaptures(true) == "RN"); } TEST_CASE("IsAttacked", "[chessarbiter/IsAttacked]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); // White third rank attacked by white CHECK(a.IsAttacked("a3", false)); CHECK(a.IsAttacked("b3", false)); CHECK(a.IsAttacked("c3", false)); CHECK(a.IsAttacked("d3", false)); CHECK(a.IsAttacked("e3", false)); CHECK(a.IsAttacked("f3", false)); CHECK(a.IsAttacked("g3", false)); CHECK(a.IsAttacked("h3", false)); // White third rank attacked by black CHECK_FALSE(a.IsAttacked("a3", true)); CHECK_FALSE(a.IsAttacked("b3", true)); CHECK_FALSE(a.IsAttacked("c3", true)); CHECK_FALSE(a.IsAttacked("d3", true)); CHECK_FALSE(a.IsAttacked("e3", true)); CHECK_FALSE(a.IsAttacked("f3", true)); CHECK_FALSE(a.IsAttacked("g3", true)); CHECK_FALSE(a.IsAttacked("h3", true)); // Black sixth rank attacked by black CHECK(a.IsAttacked("a6", true)); CHECK(a.IsAttacked("b6", true)); CHECK(a.IsAttacked("c6", true)); CHECK(a.IsAttacked("d6", true)); CHECK(a.IsAttacked("e6", true)); CHECK(a.IsAttacked("f6", true)); CHECK(a.IsAttacked("g6", true)); CHECK(a.IsAttacked("h6", true)); // Black sixth rank attacked by white CHECK_FALSE(a.IsAttacked("a6", false)); CHECK_FALSE(a.IsAttacked("b6", false)); CHECK_FALSE(a.IsAttacked("c6", false)); CHECK_FALSE(a.IsAttacked("d6", false)); CHECK_FALSE(a.IsAttacked("e6", false)); CHECK_FALSE(a.IsAttacked("f6", false)); CHECK_FALSE(a.IsAttacked("g6", false)); CHECK_FALSE(a.IsAttacked("h6", false)); // Remove a pawn for black a.Setup("rnbqkbnr/1ppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.IsAttacked("a3", false)); CHECK(a.IsAttacked("a3", true)); CHECK_FALSE(a.IsAttacked("a4", false)); CHECK(a.IsAttacked("a4", true)); // Remove another pawn for black a.Setup("rnbqkbnr/pppp1ppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.IsAttacked("a3", true)); CHECK(a.IsAttacked("h4", true)); CHECK(a.IsAttacked("a3", false)); CHECK_FALSE(a.IsAttacked("h4", false)); // Add a crazy black knight a.Setup("rnbqkbnr/pppppppp/8/8/8/4n3/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.IsAttacked("d1", true)); CHECK_FALSE(a.IsAttacked("e1", true)); CHECK(a.IsAttacked("f1", true)); CHECK_FALSE(a.IsAttacked("f2", true)); CHECK_FALSE(a.IsAttacked("d1", false)); // White can't attack is own pieces } TEST_CASE("ListLegalMoves", "[chessarbiter/ListLegalMoves]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); std::vector moves = a.ListLegalMoves(false); REQUIRE(moves.size() == 20); CHECK(std::find(moves.begin(), moves.end(), "e2e4") != moves.end()); CHECK(std::find(moves.begin(), moves.end(), "e2e3") != moves.end()); CHECK(std::find(moves.begin(), moves.end(), "b1c3") != moves.end()); CHECK_FALSE(std::find(moves.begin(), moves.end(), "d1d3") != moves.end()); // White Short Castle possible a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK11R w KQkq - 0 1"); moves = a.ListLegalMoves(false); REQUIRE(moves.size() == 22); CHECK(std::find(moves.begin(), moves.end(), "e1g1") != moves.end()); // White Short Castle impossible a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK11R w Qkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1g1") != moves.end()); // White Short Castle impossible 2 a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK1NR w KQkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1g1") != moves.end()); // White Short Castle impossible 3 (queen attacks by black) a.Setup("rnbqkbnr/pppppqpp/8/8/8/8/PPPPP1PP/RNBQK11R w KQkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1g1") != moves.end()); // White Long Castle possible a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/R3KNBR w KQkq - 0 1"); moves = a.ListLegalMoves(false); REQUIRE(moves.size() == 23); CHECK(find(moves.begin(), moves.end(), "e1c1") != moves.end()); // White Long Castle impossible a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/R3KBNR w Kkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1c1") != moves.end()); // White Long Castle impossible 2 a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RN2KBNR w KQkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1c1") != moves.end()); // White Long Castle impossible 3 (rook attacks by black) a.Setup("rnbqkbnr/pprppppp/8/8/8/8/PP1PPPPP/R3KBNR w KQkq - 0 1"); moves = a.ListLegalMoves(false); CHECK_FALSE(std::find(moves.begin(), moves.end(), "e1c1") != moves.end()); } TEST_CASE("IsPlayable", "[chessarbiter/IsPlayable]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.IsPlayable()); a.Setup("8/8/1q1k4/8/8/8/5K2/8 w - - 0 1"); CHECK(a.IsPlayable()); a.Setup("8/8/3k4/3q4/8/8/3K4/8 b - - 0 1"); CHECK_FALSE(a.IsPlayable()); a.Setup("8/8/3k4/3q4/8/8/3R4/8 b - - 0 1"); CHECK_FALSE(a.IsPlayable()); a.Setup("8/8/3k4/3q4/8/8/5K2/4K3 b - - 0 1"); CHECK_FALSE(a.IsPlayable()); a.Setup("1k6/8/3k4/3q4/8/8/5K2/8 b - - 0 1"); CHECK_FALSE(a.IsPlayable()); } TEST_CASE("Play Basic", "[chessarbiter/Play]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); // White turn CHECK(a.Play("e2e3")); CHECK(a.GetFEN() == "rnbqkbnr/pppppppp/8/8/8/4P3/PPPP1PPP/RNBQKBNR b KQkq - 0 1"); CHECK_FALSE(a.Play("d2d3")); // Black turn CHECK(a.GetFEN() == "rnbqkbnr/pppppppp/8/8/8/4P3/PPPP1PPP/RNBQKBNR b KQkq - 0 1"); // Black turn CHECK(a.Play("e7e5")); CHECK(a.GetFEN() == "rnbqkbnr/pppp1ppp/8/4p3/8/4P3/PPPP1PPP/RNBQKBNR w KQkq e6 0 2"); CHECK_FALSE(a.Play("d7d6")); // White turn CHECK(a.GetFEN() == "rnbqkbnr/pppp1ppp/8/4p3/8/4P3/PPPP1PPP/RNBQKBNR w KQkq e6 0 2"); // White turn CHECK(a.Play("b1c3")); CHECK(a.GetFEN() == "rnbqkbnr/pppp1ppp/8/4p3/8/2N1P3/PPPP1PPP/R1BQKBNR b KQkq - 1 2"); } TEST_CASE("IsCheckmate", "[chessarbiter/IsCheckmate]") { ChessArbiter a; // There is no checkmate a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK_FALSE(a.IsCheckMate()); // Ensure fen did not change CHECK(a.GetFEN() == "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); // There is a checkmate a.Setup("r1bqkbnr/1ppp1Qpp/p1n5/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4"); CHECK(a.IsCheckMate()); CHECK(a.GetFEN() == "r1bqkbnr/1ppp1Qpp/p1n5/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4"); // There is a checkmate a.Setup("1nb1kbnr/1p3ppp/2p1p3/3p4/2P4B/2qP4/3RPPPP/1r2KBNR w Kk - 0 19"); CHECK(a.IsCheckMate()); CHECK(a.GetFEN() == "1nb1kbnr/1p3ppp/2p1p3/3p4/2P4B/2qP4/3RPPPP/1r2KBNR w Kk - 0 19"); // There is no checkmate a.Setup("1nb1kbnr/1p3ppp/2p1p3/3p4/1QP4B/2qP4/3RPPPP/r3KBNR w Kk - 2 18"); CHECK_FALSE(a.IsCheckMate()); CHECK(a.GetFEN() == "1nb1kbnr/1p3ppp/2p1p3/3p4/1QP4B/2qP4/3RPPPP/r3KBNR w Kk - 2 18"); // There is a checkmate a.Setup("r3qbr1/p1p1pkp1/1p2p1p1/8/8/8/PPPPP1PP/RNBQ1RK1 b - - 1 1"); CHECK(a.IsCheckMate()); CHECK(a.GetFEN() == "r3qbr1/p1p1pkp1/1p2p1p1/8/8/8/PPPPP1PP/RNBQ1RK1 b - - 1 1"); } TEST_CASE("IsDrawByFiftyMoveRule", "[chessarbiter/IsDrawByFiftyMoveRule]") { ChessArbiter a; a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK_FALSE(a.IsDrawByFiftyMoveRule()); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 99 1"); CHECK_FALSE(a.IsDrawByFiftyMoveRule()); a.Play("b1c3"); CHECK(a.IsDrawByFiftyMoveRule()); a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 100 1"); CHECK(a.IsDrawByFiftyMoveRule()); } TEST_CASE("IsDrawByNoMoves", "[chessarbiter/IsDrawByNoMoves]") { ChessArbiter a; // No move for black a.Setup("8/8/8/8/8/8/5K1p/7k b - - 0 1"); CHECK(a.IsDrawByNoMoves()); // But move for white a.Setup("8/8/8/8/8/8/5K1p/7k w - - 0 1"); CHECK_FALSE(a.IsDrawByNoMoves()); // No move for white a.Setup("8/8/7r/2K5/b7/2k5/6q1/8 w - - 0 1"); CHECK(a.IsDrawByNoMoves()); // But move for black a.Setup("8/8/7r/2K5/b7/2k5/6q1/8 b - - 0 1"); CHECK_FALSE(a.IsDrawByNoMoves()); } TEST_CASE("IsDrawByRepetitions", "[chessarbiter/IsDrawByRepetitions]") { ChessArbiter a; // One time a.Setup("8/3kp3/8/8/4P3/3K4/8/8 w - - 0 1"); a.Play("d3d4"); a.Play("d7d6"); CHECK_FALSE(a.IsDrawByRepetitions()); // Two time a.Play("d4d3"); a.Play("d6d7"); CHECK_FALSE(a.IsDrawByRepetitions()); a.Play("d3d4"); a.Play("d7d6"); CHECK_FALSE(a.IsDrawByRepetitions()); // Three time a.Play("d4d3"); a.Play("d6d7"); CHECK(a.IsDrawByRepetitions()); } TEST_CASE("SimpleCapture", "[SimplePieceCapture]") { ChessArbiter a; a.Setup("rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"); // Ensure capture works a.Play("e4d5"); CHECK(a.GetFEN() == "rnbqkbnr/ppp1pppp/8/3P4/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2"); CHECK(a.GetCapture() == 'p'); CHECK_FALSE(a.WasEnPassant()); } TEST_CASE("SimpleCastle", "[SimpleCastle]") { ChessArbiter a; a.Setup("rnbqkbnr/ppp1p1pp/8/3p1p2/4P3/3B1N2/PPPP1PPP/RNBQK2R w KQkq - 0 2"); // White CHECK(a.Play("e1g1")); CHECK(a.GetFEN() == "rnbqkbnr/ppp1p1pp/8/3p1p2/4P3/3B1N2/PPPP1PPP/RNBQ1RK1 b kq - 1 2"); a.Setup("rnbqkbnr/ppp1p1pp/8/3p1p2/4P3/1BNB1N2/PPPPQPPP/R3K2R w KQkq - 0 2"); CHECK(a.Play("e1c1")); CHECK(a.GetFEN() == "rnbqkbnr/ppp1p1pp/8/3p1p2/4P3/1BNB1N2/PPPPQPPP/2KR3R b kq - 1 2"); // Black a.Setup( "r3k2r/pppnp1pp/1bq1bn2/3p1p2/4P3/1BNB1N2/PPPPQPPP/R3K2R b KQkq - 0 2"); CHECK(a.Play("e8g8")); CHECK(a.GetFEN() == "r4rk1/pppnp1pp/1bq1bn2/3p1p2/4P3/1BNB1N2/PPPPQPPP/R3K2R w KQ - 1 3"); a.Setup( "r3k2r/pppnp1pp/1bq1bn2/3p1p2/4P3/1BNB1N2/PPPPQPPP/R3K2R b KQkq - 0 2"); CHECK(a.Play("e8c8")); CHECK(a.GetFEN() == "2kr3r/pppnp1pp/1bq1bn2/3p1p2/4P3/1BNB1N2/PPPPQPPP/R3K2R w KQ - 1 3"); } TEST_CASE("SimpleEnPassant", "[SimpleEnPassant]") { ChessArbiter a; // White capture a.Setup("rnbqkbnr/ppppp1pp/8/4Pp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 2"); CHECK(a.Play("e5f6")); CHECK(a.GetFEN() == "rnbqkbnr/ppppp1pp/5P2/8/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2"); CHECK(a.GetCapture() == 'p'); CHECK(a.WasEnPassant()); // Black capture a.Setup("rnbqkbnr/ppppp1pp/8/8/4Pp2/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"); CHECK(a.Play("f4e3")); CHECK(a.GetFEN() == "rnbqkbnr/ppppp1pp/8/8/8/4p3/PPPP1PPP/RNBQKBNR w KQkq - 0 2"); CHECK(a.GetCapture() == 'P'); CHECK(a.WasEnPassant()); // Check en_passant is set a.Setup( "r3k2r/1pqbbp1p/1nn1p1p1/p2pP3/3P1PP1/PP1B4/1B1NN2P/R2Q1RK1 b kq - 2 14"); CHECK(a.Play("f7f5")); CHECK(a.GetFEN() == "r3k2r/1pqbb2p/1nn1p1p1/p2pPp2/3P1PP1/PP1B4/1B1NN2P/" "R2Q1RK1 w kq f6 0 15"); CHECK_FALSE(a.WasEnPassant()); } TEST_CASE("ParseSAN", "[ParseSAN]") { ChessArbiter a; // Initial position test a.Setup("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); CHECK(a.ParseSAN("d4") == "d2d4"); CHECK(a.ParseSAN("e3") == "e2e3"); CHECK(a.ParseSAN("e4") == "e2e4"); CHECK(a.ParseSAN("Nc3") == "b1c3"); CHECK(a.ParseSAN("Nf3") == "g1f3"); // Check when two similar piece can go to the same square a.Setup("rnbqkbnr/pppppppp/8/8/P6P/7R/1PPPPPP1/RNBQKBN1 w Qkq - 0 1"); CHECK(a.ParseSAN("Raa3") == "a1a3"); CHECK(a.ParseSAN("Rha3") == "h3a3"); a.Setup("rnbqkbnr/pppppppp/8/8/P6P/R7/1PPPPPP1/RNBQKBN1 w Qkq - 0 1"); CHECK(a.ParseSAN("R1a2") == "a1a2"); CHECK(a.ParseSAN("R3a2") == "a3a2"); a.Setup("r1bqkb1r/pppppppp/5n2/8/P6P/R1N5/1PPPPnP1/R1BQKBN1 b Qkq - 0 1"); CHECK(a.ParseSAN("N6e4") == "f6e4"); CHECK(a.ParseSAN("N2e4") == "f2e4"); // Castling a.Setup("rnbqkbnr/pppppppp/8/8/8/4NB2/PPPPPPPP/RNBQK2R w KQkq - 0 1"); CHECK(a.ParseSAN("O-O") == "e1g1"); a.Setup("rnbqkbnr/pppppppp/8/8/8/2NBQ3/PPPPPPPP/R3KBNR w KQkq - 0 1"); CHECK(a.ParseSAN("O-O-O") == "e1c1"); a.Setup("rnbqk2r/pppppppp/4bn2/8/8/2NBQ3/PPPPPPPP/R3KBNR b KQkq - 0 1"); CHECK(a.ParseSAN("O-O") == "e8g8"); a.Setup("r3kb1r/pppppppp/2qnbn2/8/8/2NBQ3/PPPPPPPP/R3KBNR b KQkq - 0 1"); CHECK(a.ParseSAN("O-O-O") == "e8c8"); // Random tests a.Setup( "r1bq1rk1/p4ppp/2p2n2/1pbPp3/3n4/P1NB3P/1PPP1PPN/R1BQ1RK1 b - - 0 10"); CHECK(a.ParseSAN("exd5") == "c6d5"); a.Setup("rnbqkbnr/pp3ppp/4p3/2pp4/3PP3/8/PPPN1PPP/R1BQKBNR w KQkq - 0 4"); CHECK(a.ParseSAN("exd5") == "e4d5"); a.Setup("1r4k1/4pp1p/6pb/1p3b2/P1P5/5P2/2P3PP/1K1R3R w - - 0 23"); CHECK(a.ParseSAN("cxb5") == "c4b5"); } TEST_CASE("Specific bugs found on a game", "[BugFixes]") { ChessArbiter a; // BUG 1 a.Setup("1k3r1r/npqbbp2/4p1p1/p2pPnNp/1P3B1P/P1PB4/5PPQ/RN2R1K1 w - - 1 19"); a.Play("e1c1"); CHECK(a.GetFEN() == "1k3r1r/npqbbp2/4p1p1/p2pPnNp/1P3B1P/P1PB4/5PPQ/RNR3K1 b - - 2 19"); CHECK(!a.WasPawnPromotion()); // BUG 2 (Promotion) a.Setup("8/k2P4/2p1ppp1/5qBp/5P1P/8/6PK/8 w - - 0 45"); a.Play("d7d8"); CHECK(a.GetFEN() == "3Q4/k7/2p1ppp1/5qBp/5P1P/8/6PK/8 b - - 0 45"); CHECK(a.WasPawnPromotion()); CHECK(a.GetSAN()=="d8=Q"); // BUG 3 (Promotion) a.Setup("8/k2P4/2p1ppp1/5qBp/5P1P/8/6PK/8 w - - 0 45"); a.Play("d7d8",'n'); CHECK(a.GetFEN() == "3N4/k7/2p1ppp1/5qBp/5P1P/8/6PK/8 b - - 0 45"); CHECK(a.WasPawnPromotion()); CHECK(a.GetSAN()=="d8=N"); // BUG 4 (Promotion) char p=a.ParseSANPromotion("d8=Q"); CHECK(p == 'Q'); p=a.ParseSANPromotion("d8=N+"); CHECK(p == 'N'); p=a.ParseSANPromotion("d8=B+"); CHECK(p == 'B'); p=a.ParseSANPromotion("h1=R"); CHECK(p == 'R'); p=a.ParseSANPromotion("a1=R"); CHECK(p == 'R'); p=a.ParseSANPromotion("c1=R"); CHECK(p == 'R'); // Bug 5 (Pin piece: the Knight on c3 cannot move so the only legal move for a white Knight is g1e2) a.Setup("r1bqk2r/pp1n1p2/3p4/1BpP2pp/1b2n2P/2N1P1B1/PP3PP1/R2QK1NR w KQkq - 3 12"); CHECK(a.ParseSAN("Ne2") == "g1e2"); a.Play("g1e2"); CHECK(a.GetFEN() == "r1bqk2r/pp1n1p2/3p4/1BpP2pp/1b2n2P/2N1P1B1/PP2NPP1/R2QK2R b KQkq - 4 12"); // Bug 6 SAN move that lead to check must have a + sign on the SAN moves a.Setup("rnb1kbnr/pppp1ppp/3qP3/8/8/8/PPP1PPPP/RNB1KBNR b KQkq - 0 4"); a.Play("d6d1"); CHECK(a.IsCheck(false)); CHECK(!a.IsCheck(!false)); CHECK(a.GetSAN()=="Qd1+"); a.Setup("rnb1kbnr/pppp1ppp/3qP3/8/8/8/PPP1PPPP/RNB1KBNR b KQkq - 0 4"); a.Play("d6d3"); CHECK(!a.IsCheck(false)); CHECK(a.GetSAN()=="Qd3"); // Bug 7 SAN move that lead to checkmate must have a # sign on the SAN moves a.Setup("rnb1k1nr/pppp1ppp/4P3/8/1b3B2/1Nq5/PPP1PPPP/R2KNB1R b kq - 16 12"); a.Play("c3e1"); CHECK(a.GetSAN()=="Qxe1#"); // Bug 8 Not a bug but just check if bishop cannot jump above pieces a.Setup("rnbqkbnr/p1pp1ppp/8/1p2p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1"); CHECK(!a.Play("f1a6")); }