mirror of
https://gitlab.com/manzerbredes/chessarbiter.git
synced 2025-04-19 03:59:42 +00:00
Init project
This commit is contained in:
commit
e9d328acf4
19 changed files with 23418 additions and 0 deletions
17
tests/CMakeLists.txt
Normal file
17
tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Configure catch3
|
||||
include_directories(./catch3/)
|
||||
add_library(catch3 SHARED ./catch3/catch_amalgamated.cpp)
|
||||
|
||||
# Add tests
|
||||
add_executable(fen_tests fen.cpp)
|
||||
target_link_libraries(fen_tests chessarbiter catch3)
|
||||
add_test(Fen_Test fen_tests)
|
||||
|
||||
add_executable(board_tests board.cpp)
|
||||
target_link_libraries(board_tests chessarbiter catch3)
|
||||
add_test(Board_Test board_tests)
|
||||
|
||||
add_executable(chessarbiter_tests chessarbiter.cpp)
|
||||
target_link_libraries(chessarbiter_tests chessarbiter catch3)
|
||||
add_test(ChessArbiter_Test chessarbiter_tests)
|
||||
|
418
tests/board.cpp
Normal file
418
tests/board.cpp
Normal file
|
@ -0,0 +1,418 @@
|
|||
#include "Board.hpp"
|
||||
#include <catch_amalgamated.hpp>
|
||||
|
||||
using namespace chessarbiter;
|
||||
|
||||
TEST_CASE("IsEmpty/AddPiece", "[board/IsEmpty/AddPiece]") {
|
||||
Board b;
|
||||
b.AddPiece('K', "a1");
|
||||
b.AddPiece('K', "a8");
|
||||
b.AddPiece('K', "c8");
|
||||
|
||||
CHECK_FALSE(b.IsEmpty("a1"));
|
||||
CHECK_FALSE(b.IsEmpty("a8"));
|
||||
CHECK_FALSE(b.IsEmpty("c8"));
|
||||
|
||||
CHECK(b.IsEmpty("a2"));
|
||||
CHECK(b.IsEmpty("a3"));
|
||||
CHECK(b.IsEmpty("a4"));
|
||||
}
|
||||
|
||||
TEST_CASE("Clear", "[board/Clear]") {
|
||||
Board b;
|
||||
b.AddPiece('K', "a1");
|
||||
b.AddPiece('A', "a8");
|
||||
b.AddPiece('Q', "c8");
|
||||
|
||||
b.Clear();
|
||||
|
||||
CHECK(b.IsEmpty("a1"));
|
||||
CHECK(b.IsEmpty("a8"));
|
||||
CHECK(b.IsEmpty("c8"));
|
||||
}
|
||||
|
||||
TEST_CASE("GetPieceAt", "[board/GetPieceAt]") {
|
||||
Board b;
|
||||
b.AddPiece('K', "a1");
|
||||
b.AddPiece('A', "a8");
|
||||
b.AddPiece('Q', "c8");
|
||||
|
||||
CHECK((b.GetPieceAt("a1")).piece == 'K');
|
||||
CHECK((b.GetPieceAt("a8")).piece == 'A');
|
||||
CHECK((b.GetPieceAt("c8")).piece == 'Q');
|
||||
|
||||
CHECK_THROWS_AS(b.GetPieceAt("a5"), chessarbiter::NoPieceFound);
|
||||
}
|
||||
|
||||
TEST_CASE("CountPiece", "[board/CountPiece]") {
|
||||
Board b;
|
||||
b.AddPiece('K', "a1");
|
||||
b.AddPiece('K', "a3");
|
||||
|
||||
CHECK(b.CountPiece('K') == 2);
|
||||
|
||||
b.AddPiece('k', "b1");
|
||||
b.AddPiece('k', "b5");
|
||||
|
||||
CHECK(b.CountPiece('k') == 2);
|
||||
|
||||
b.AddPiece('b', "h8");
|
||||
b.AddPiece('b', "h7");
|
||||
|
||||
CHECK(b.CountPiece('b') == 2);
|
||||
CHECK(b.CountPiece('p') == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("GetKingLocation", "[board/GetKingLocation]") {
|
||||
Board b;
|
||||
|
||||
b.AddPiece('k', "a1");
|
||||
CHECK(b.GetKingLocation(true) == "a1");
|
||||
|
||||
b.AddPiece('K', "h1");
|
||||
CHECK(b.GetKingLocation(false) == "h1");
|
||||
|
||||
b.Clear();
|
||||
CHECK_THROWS_AS(b.GetKingLocation(true), NoPieceFound);
|
||||
}
|
||||
|
||||
TEST_CASE("RemovePiece", "[board/RemovePiece]") {
|
||||
Board b;
|
||||
|
||||
b.AddPiece('k', "a1");
|
||||
b.AddPiece('p', "a2");
|
||||
|
||||
REQUIRE(!b.IsEmpty("a1"));
|
||||
REQUIRE(!b.IsEmpty("a2"));
|
||||
|
||||
b.RemovePiece("a1");
|
||||
|
||||
REQUIRE(b.IsEmpty("a1"));
|
||||
REQUIRE(!b.IsEmpty("a2"));
|
||||
}
|
||||
|
||||
TEST_CASE("Move", "[board/Move]") {
|
||||
Board b;
|
||||
|
||||
b.AddPiece('k', "a1");
|
||||
b.AddPiece('p', "a2");
|
||||
|
||||
REQUIRE(!b.IsEmpty("a1"));
|
||||
REQUIRE(!b.IsEmpty("a2"));
|
||||
|
||||
// Nothing should happend since no piece on a3 (not even a throw)
|
||||
CHECK_NOTHROW(b.Move("a3c4"));
|
||||
REQUIRE(!b.IsEmpty("a1"));
|
||||
REQUIRE(!b.IsEmpty("a2"));
|
||||
|
||||
b.Move("a1a2");
|
||||
REQUIRE(b.IsEmpty("a1"));
|
||||
REQUIRE(!b.IsEmpty("a2"));
|
||||
|
||||
b.Move("a2h8");
|
||||
REQUIRE(b.IsEmpty("a2"));
|
||||
REQUIRE(!b.IsEmpty("h8"));
|
||||
}
|
||||
|
||||
TEST_CASE("GetPlayerPieces", "[board/GetPlayerPieces]") {
|
||||
Board b;
|
||||
b.AddPiece('P', "a2");
|
||||
b.AddPiece('B', "b2");
|
||||
b.AddPiece('k', "c2");
|
||||
|
||||
std::vector<Piece> pieces = b.GetPlayerPieces(false);
|
||||
REQUIRE(pieces.size() == 2);
|
||||
REQUIRE(b.GetPlayerPieces(true).size() == 1);
|
||||
|
||||
bool found = false;
|
||||
for (Piece &p : pieces) {
|
||||
if (p.coord == "a2" && p.piece == 'P') {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
CHECK(found);
|
||||
found = false;
|
||||
|
||||
for (Piece &p : pieces) {
|
||||
if (p.coord == "b2" && p.piece == 'B') {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
CHECK(found);
|
||||
found = false;
|
||||
}
|
||||
|
||||
TEST_CASE("IsMovePossible", "[board/IsMovePossible]") {
|
||||
Board b;
|
||||
b.AddPiece('P', "a2");
|
||||
|
||||
// Pawn white
|
||||
CHECK(b.IsMovePossible("a2a3"));
|
||||
CHECK_FALSE(b.IsMovePossible("a2a1")); // Can't go backward
|
||||
CHECK(b.IsMovePossible(
|
||||
"a2b3")); // Not that Board is not in charge of pawn singularities
|
||||
CHECK(b.IsMovePossible("a2a4"));
|
||||
b.AddPiece('p', "a3");
|
||||
CHECK_FALSE(b.IsMovePossible("a2a4")); // Now we can't
|
||||
b.AddPiece('P', "b3");
|
||||
CHECK_FALSE(b.IsMovePossible("a2b3")); // Now we can't
|
||||
b.Clear();
|
||||
b.AddPiece('P', "a2");
|
||||
b.AddPiece('p', "b3"); // Opposite color!
|
||||
CHECK(b.IsMovePossible("a2b3")); // Now we can
|
||||
|
||||
// Pawn black
|
||||
b.Clear();
|
||||
b.AddPiece('p', "a7");
|
||||
CHECK(b.IsMovePossible("a7a6"));
|
||||
CHECK_FALSE(b.IsMovePossible("a7a8")); // Can't go backward
|
||||
CHECK(b.IsMovePossible(
|
||||
"a7b6")); // Not that Board is not in charge of pawn singularities
|
||||
CHECK(b.IsMovePossible("a7a5"));
|
||||
b.AddPiece('p', "a6");
|
||||
CHECK_FALSE(b.IsMovePossible("a7a5")); // Now we can't
|
||||
b.AddPiece('p', "b6");
|
||||
CHECK_FALSE(b.IsMovePossible("a7b6")); // Now we can't
|
||||
b.Clear();
|
||||
b.AddPiece('p', "a7");
|
||||
b.AddPiece('P', "b6"); // Opposite color!
|
||||
CHECK(b.IsMovePossible("a7b6")); // Now we can
|
||||
|
||||
// Bishop
|
||||
b.Clear();
|
||||
b.AddPiece('b', "d5");
|
||||
CHECK(b.IsMovePossible("d5h1"));
|
||||
CHECK(b.IsMovePossible("d5a8"));
|
||||
CHECK(b.IsMovePossible("d5a2"));
|
||||
CHECK(b.IsMovePossible("d5g8"));
|
||||
b.AddPiece('q', "b7"); // We block the piece in every directions
|
||||
b.AddPiece('q', "g2");
|
||||
b.AddPiece('q', "b3");
|
||||
b.AddPiece('q', "f7");
|
||||
CHECK_FALSE(b.IsMovePossible("d5h1"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a2"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5g8"));
|
||||
// No rook moves
|
||||
CHECK_FALSE(b.IsMovePossible("d5a5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5h5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d1"));
|
||||
|
||||
// Rook
|
||||
b.Clear();
|
||||
b.AddPiece('r', "d5");
|
||||
CHECK(b.IsMovePossible("d5a5"));
|
||||
CHECK(b.IsMovePossible("d5h5"));
|
||||
CHECK(b.IsMovePossible("d5d8"));
|
||||
CHECK(b.IsMovePossible("d5d1"));
|
||||
b.AddPiece('q', "b5"); // We block the piece in every directions
|
||||
b.AddPiece('q', "g5");
|
||||
b.AddPiece('q', "d7");
|
||||
b.AddPiece('q', "d2");
|
||||
CHECK_FALSE(b.IsMovePossible("d5a5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5h5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d1"));
|
||||
// No bishop moves
|
||||
CHECK_FALSE(b.IsMovePossible("d5h1"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a2"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5g8"));
|
||||
|
||||
// Queen like bishop
|
||||
b.Clear();
|
||||
b.AddPiece('q', "d5");
|
||||
CHECK(b.IsMovePossible("d5h1"));
|
||||
CHECK(b.IsMovePossible("d5a8"));
|
||||
CHECK(b.IsMovePossible("d5a2"));
|
||||
CHECK(b.IsMovePossible("d5g8"));
|
||||
b.AddPiece('q', "b7"); // We block the piece in every directions
|
||||
b.AddPiece('q', "g2");
|
||||
b.AddPiece('q', "b3");
|
||||
b.AddPiece('q', "f7");
|
||||
CHECK_FALSE(b.IsMovePossible("d5h1"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5a2"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5g8"));
|
||||
|
||||
// Queen like rook
|
||||
b.Clear();
|
||||
b.AddPiece('q', "d5");
|
||||
CHECK(b.IsMovePossible("d5a5"));
|
||||
CHECK(b.IsMovePossible("d5h5"));
|
||||
CHECK(b.IsMovePossible("d5d8"));
|
||||
CHECK(b.IsMovePossible("d5d1"));
|
||||
b.AddPiece('q', "b5"); // We block the piece in every directions
|
||||
b.AddPiece('q', "g5");
|
||||
b.AddPiece('q', "d7");
|
||||
b.AddPiece('q', "d2");
|
||||
CHECK_FALSE(b.IsMovePossible("d5a5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5h5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d8"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d1"));
|
||||
|
||||
// Knight
|
||||
b.Clear();
|
||||
b.AddPiece('n', "d5");
|
||||
CHECK(b.IsMovePossible("d5e7"));
|
||||
CHECK(b.IsMovePossible("d5c7"));
|
||||
CHECK(b.IsMovePossible("d5b6"));
|
||||
CHECK(b.IsMovePossible("d5b4"));
|
||||
CHECK(b.IsMovePossible("d5c3"));
|
||||
CHECK(b.IsMovePossible("d5e3"));
|
||||
CHECK(b.IsMovePossible("d5f4"));
|
||||
CHECK(b.IsMovePossible("d5f6"));
|
||||
// Not possible
|
||||
CHECK_FALSE(b.IsMovePossible("d5d7"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5d3"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5b5"));
|
||||
CHECK_FALSE(b.IsMovePossible("d5f5"));
|
||||
|
||||
// King
|
||||
b.Clear();
|
||||
b.AddPiece('k', "d5");
|
||||
CHECK(b.IsMovePossible("d5d6"));
|
||||
CHECK(b.IsMovePossible("d5c6"));
|
||||
CHECK(b.IsMovePossible("d5e6"));
|
||||
CHECK(b.IsMovePossible("d5c5"));
|
||||
CHECK(b.IsMovePossible("d5e5"));
|
||||
CHECK(b.IsMovePossible("d5d4"));
|
||||
CHECK(b.IsMovePossible("d5c4"));
|
||||
CHECK(b.IsMovePossible("d5e4"));
|
||||
|
||||
// Moving a piece at the same place is not possible
|
||||
CHECK_FALSE(b.IsMovePossible("d5d5"));
|
||||
}
|
||||
|
||||
TEST_CASE("ListPossibleMoves", "[board/ListPossibleMoves]") {
|
||||
Board b;
|
||||
b.AddPiece('K', "a1");
|
||||
b.AddPiece('K', "a8");
|
||||
b.AddPiece('K', "h1");
|
||||
b.AddPiece('K', "h8");
|
||||
b.AddPiece('k', "d5"); // Black piece
|
||||
|
||||
std::vector<std::string> moves = b.ListPossibleMoves(false);
|
||||
REQUIRE(moves.size() == 12);
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1a2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1b2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1b1") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8a7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8b8") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8b7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8g7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8g8") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8h7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1h2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1g1") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1g2") != moves.end());
|
||||
|
||||
b.Clear();
|
||||
b.AddPiece('k', "a1");
|
||||
b.AddPiece('k', "a8");
|
||||
b.AddPiece('k', "h1");
|
||||
b.AddPiece('k', "h8");
|
||||
b.AddPiece('K', "d5"); // White piece
|
||||
|
||||
moves = b.ListPossibleMoves(true);
|
||||
REQUIRE(moves.size() == 12);
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1a2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1b2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a1b1") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8a7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8b8") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "a8b7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8g7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8g8") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h8h7") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1h2") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1g1") != moves.end());
|
||||
CHECK(std::find(moves.begin(), moves.end(), "h1g2") != moves.end());
|
||||
}
|
||||
|
||||
TEST_CASE("Serialize", "[board/Serialize]") {
|
||||
Board b;
|
||||
b.AddPiece('p', "a8");
|
||||
CHECK(b.Serialize() == "p "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" ");
|
||||
b.AddPiece('P', "a1");
|
||||
CHECK(b.Serialize() == "p "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"P ");
|
||||
b.AddPiece('k', "d5");
|
||||
CHECK(b.Serialize() == "p "
|
||||
" "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"P ");
|
||||
b.AddPiece('Q', "d7");
|
||||
CHECK(b.Serialize() == "p "
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"P ");
|
||||
b.AddPiece('p', "h2");
|
||||
CHECK(b.Serialize() == "p "
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" p"
|
||||
"P ");
|
||||
b.AddPiece('k', "h8");
|
||||
CHECK(b.Serialize() == "p k"
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" p"
|
||||
"P ");
|
||||
b.AddPiece('N', "b2");
|
||||
CHECK(b.Serialize() == "p k"
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" N p"
|
||||
"P ");
|
||||
b.AddPiece('n', "c2");
|
||||
CHECK(b.Serialize() == "p k"
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" "
|
||||
" Nn p"
|
||||
"P ");
|
||||
b.AddPiece('b', "c3");
|
||||
CHECK(b.Serialize() == "p k"
|
||||
" Q "
|
||||
" "
|
||||
" k "
|
||||
" "
|
||||
" b "
|
||||
" Nn p"
|
||||
"P ");
|
||||
}
|
||||
|
9929
tests/catch3/catch_amalgamated.cpp
Normal file
9929
tests/catch3/catch_amalgamated.cpp
Normal file
File diff suppressed because it is too large
Load diff
11652
tests/catch3/catch_amalgamated.hpp
Normal file
11652
tests/catch3/catch_amalgamated.hpp
Normal file
File diff suppressed because it is too large
Load diff
302
tests/chessarbiter.cpp
Normal file
302
tests/chessarbiter.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
#include "ChessArbiter.hpp"
|
||||
#include <catch_amalgamated.hpp>
|
||||
|
||||
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<std::string> 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(), "O-O") != 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(), "O-O") != 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(), "O-O") != 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(), "O-O") != 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(), "O-O-O") != 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(), "O-O-O") != 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(), "O-O-O") != 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(), "O-O-O") != 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 - 0 2");
|
||||
CHECK_FALSE(a.Play("d7d6")); // White turn
|
||||
CHECK(a.GetFEN() ==
|
||||
"rnbqkbnr/pppp1ppp/8/4p3/8/4P3/PPPP1PPP/RNBQKBNR w KQkq - 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");
|
||||
}
|
91
tests/fen.cpp
Normal file
91
tests/fen.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "Fen.hpp"
|
||||
#include <catch_amalgamated.hpp>
|
||||
|
||||
using namespace chessarbiter;
|
||||
|
||||
TEST_CASE("Serializer", "[fen/serialize]") {
|
||||
FEN f;
|
||||
f.board = "p p p"
|
||||
"p p"
|
||||
" "
|
||||
"QQQQQQQQ"
|
||||
"kpkpkpkp"
|
||||
" "
|
||||
"p p r b "
|
||||
" R";
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R w KQkq - 0 1");
|
||||
|
||||
f.white_castle_short = false;
|
||||
f.white_castle_long = false;
|
||||
f.black_castle_short = false;
|
||||
f.black_castle_long = false;
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R w - - 0 1");
|
||||
|
||||
f.en_passant = "a3";
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R w - a3 0 1");
|
||||
|
||||
f.player = true;
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b - a3 0 1");
|
||||
|
||||
f.halfmove = 5;
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b - a3 5 1");
|
||||
|
||||
f.move = 5;
|
||||
REQUIRE(FENParser::Serialize(f) ==
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b - a3 5 5");
|
||||
}
|
||||
|
||||
TEST_CASE("Parse", "[fen/parse]") {
|
||||
FEN f;
|
||||
f = FENParser::Parse(
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b - a3 5 5");
|
||||
|
||||
REQUIRE(f.board == "p p p"
|
||||
"p p"
|
||||
" "
|
||||
"QQQQQQQQ"
|
||||
"kpkpkpkp"
|
||||
" "
|
||||
"p p r b "
|
||||
" R");
|
||||
CHECK(f.white_castle_short == false);
|
||||
CHECK(f.white_castle_long == false);
|
||||
CHECK(f.black_castle_short == false);
|
||||
CHECK(f.black_castle_long == false);
|
||||
CHECK(f.move == 5);
|
||||
CHECK(f.halfmove == 5);
|
||||
CHECK(f.player == true);
|
||||
|
||||
f = FENParser::Parse(
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b k a3 5 5");
|
||||
CHECK(f.white_castle_short == false);
|
||||
CHECK(f.white_castle_long == false);
|
||||
CHECK(f.black_castle_short == true);
|
||||
CHECK(f.black_castle_long == false);
|
||||
|
||||
f = FENParser::Parse(
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b qk a3 5 5");
|
||||
CHECK(f.white_castle_short == false);
|
||||
CHECK(f.white_castle_long == false);
|
||||
CHECK(f.black_castle_short == true);
|
||||
CHECK(f.black_castle_long == true);
|
||||
|
||||
f = FENParser::Parse(
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b Kqk a3 5 5");
|
||||
CHECK(f.white_castle_short == true);
|
||||
CHECK(f.white_castle_long == false);
|
||||
CHECK(f.black_castle_short == true);
|
||||
CHECK(f.black_castle_long == true);
|
||||
|
||||
f = FENParser::Parse(
|
||||
"p4p1p/p6p/8/QQQQQQQQ/kpkpkpkp/8/p1p1r1b1/7R b KQqk a3 5 5");
|
||||
CHECK(f.white_castle_short == true);
|
||||
CHECK(f.white_castle_long == true);
|
||||
CHECK(f.black_castle_short == true);
|
||||
CHECK(f.black_castle_long == true);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue