diff --git a/main/adapter/lib/Sentio.cpp b/main/adapter/lib/Sentio.cpp index db85a54..60e8f90 100644 --- a/main/adapter/lib/Sentio.cpp +++ b/main/adapter/lib/Sentio.cpp @@ -118,27 +118,50 @@ bool eboard::Sentio::takeBackMove(std::vector const& occupiedSquares) { void eboard::Sentio::checkValidMove(std::vector const& expectedSquares, std::vector const& occupiedSquares) { std::vector missing; - std::set_difference(expectedSquares.begin(), expectedSquares.end(), occupiedSquares.begin(), occupiedSquares.end(), - std::inserter(missing, missing.begin())); std::vector extra; - std::set_difference(occupiedSquares.begin(), occupiedSquares.end(), expectedSquares.begin(), expectedSquares.end(), - std::inserter(extra, extra.begin())); - if (!nonCaptureMove(missing, extra)) { + setDifference(expectedSquares, occupiedSquares, missing, extra); + if (!nonCaptureMove(occupiedSquares, missing, extra)) { if (!captureMove(missing, extra)) { incompleteMove(missing, extra); } } } +void eboard::Sentio::setDifference(const std::vector& expectedSquares, + const std::vector& occupiedSquares, std::vector& missing, + std::vector& extra) { + std::set_difference(expectedSquares.begin(), expectedSquares.end(), occupiedSquares.begin(), occupiedSquares.end(), + std::inserter(missing, missing.begin())); + std::set_difference(occupiedSquares.begin(), occupiedSquares.end(), expectedSquares.begin(), expectedSquares.end(), + std::inserter(extra, extra.begin())); +} + static uint8_t toBoardArraySquare(uint8_t sq) { uint8_t file = sq & 7; uint8_t rank = sq / 8; return (7 - rank) * 8 + file; } -bool eboard::Sentio::nonCaptureMove(std::vector const& missing, std::vector const& extra) { +bool eboard::Sentio::nonCaptureMove(std::vector const& occupiedSquares, std::vector const& missing, + std::vector const& extra) { if (capturePiece == nullptr && missing.size() == 1 && extra.size() == 1) { - if (!makeMove(missing[0], extra[0])) { + if (makeMove(missing[0], extra[0])) { + std::vector expectedSquares = board.getOccupiedSquares(); + if (expectedSquares == occupiedSquares) { + callCallback(toBoardArray(board)); + } else { + // castles - need rooks to move as well + std::vector miss; + std::vector ex; + setDifference(expectedSquares, occupiedSquares, miss, ex); + if (miss.size() == 1 && ex.size() == 1) { + std::array boardArray = toBoardArray(board); + boardArray[toBoardArraySquare(ex[0])] = PIECE_TO_STONE_ID.at(board.getPiece(miss[0])); + boardArray[toBoardArraySquare(miss[0])] = 0; + callCallback(boardArray); + } + } + } else { std::array boardArray = toBoardArray(board); boardArray[toBoardArraySquare(extra[0])] = board.getPiece(missing[0]); boardArray[toBoardArraySquare(missing[0])] = 0; @@ -182,12 +205,16 @@ bool eboard::Sentio::captureMove(std::vector const& missing, std::vecto uint8_t fromSquare = capturePiece->getFromSquare(); uint8_t toSquare = capturePiece->getToSquare(); capturePiece.reset(); - return makeMove(fromSquare, toSquare); + bool result = makeMove(fromSquare, toSquare); + callCallback(toBoardArray(board)); + return result; } else if (capturePiece != nullptr && isPossibleEpCapture(missing, extra)) { uint8_t fromSquare = capturePiece->getFromSquare(); uint8_t toSquare = extra[0]; capturePiece.reset(); - return makeMove(fromSquare, toSquare); + bool result = makeMove(fromSquare, toSquare); + callCallback(toBoardArray(board)); + return result; } return false; } @@ -197,9 +224,7 @@ bool eboard::Sentio::makeMove(uint8_t fromSquare, uint8_t toSquare) { int i = 1; for (uint32_t move : moves) { if (fromSquare == get_move_source_64(move) && toSquare == get_move_target_64(move)) { - board.make_move(move); - callCallback(toBoardArray(board)); - return true; + return board.make_move(move); } i++; } diff --git a/main/adapter/lib/Sentio.h b/main/adapter/lib/Sentio.h index d80440a..754e586 100644 --- a/main/adapter/lib/Sentio.h +++ b/main/adapter/lib/Sentio.h @@ -30,9 +30,12 @@ class Sentio { static std::vector toSquares(const std::array& occupied); void callCallback(std::array const& boardArray); static std::array toBoardArray(chess::Chess0x88& chessBoard); - bool takeBackMove(std::vector const &occupiedSquares); + bool takeBackMove(std::vector const& occupiedSquares); void checkValidMove(std::vector const& expectedSquares, std::vector const& occupiedSquares); - bool nonCaptureMove(std::vector const& missing, std::vector const& extra); + static void setDifference(const std::vector& expectedSquares, const std::vector& occupiedSquares, + std::vector& missing, std::vector& extra) ; + bool nonCaptureMove(std::vector const& occupied, std::vector const& missing, + std::vector const& extra); bool captureMove(std::vector const& missing, std::vector const& extra); void incompleteMove(std::vector const& missing, std::vector const& extra); bool makeMove(uint8_t fromSquare, uint8_t toSquare); diff --git a/main/adapter/test/SentioTest.cpp b/main/adapter/test/SentioTest.cpp index 98d1aa1..a23d1bd 100644 --- a/main/adapter/test/SentioTest.cpp +++ b/main/adapter/test/SentioTest.cpp @@ -139,6 +139,17 @@ TEST_F(SentioTest, captureMove) { thenLastReceivedBoardShouldBe("rnbqkbnr/ppp1pppp/8/3P4/8/8/PPPP1PPP/RNBQKBNR"); } +TEST_F(SentioTest, castlesMove) { + givenAnInstance("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 4 4"); + givenOccupiedIsCalledWith("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ3R"); // Ke1 up + givenOccupiedIsCalledWith("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ2KR"); // Kg1 down + thenLastReceivedBoardShouldBe("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ2KR"); + givenOccupiedIsCalledWith("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ2K1"); // Rh1 up + thenLastReceivedBoardShouldBe("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ2K1"); + givenOccupiedIsCalledWith("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ1RK1"); // Rf1 down + thenLastReceivedBoardShouldBe("r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ1RK1"); +} + TEST_F(SentioTest, gameSequenceThreeCaptureMovesApart) { givenAnInstance(); // game sequence: 1. e4 c5 2. Nf3 d6 3. Bb5+ Bd7 4. Bxd7+ Qxd7 5. h4 Qc6 6. h5 Qxe4+