From 06ca41649f209e731441a0e4ea0f179c891278ec Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Mon, 30 Jul 2007 13:23:09 +0200 Subject: [PATCH] Added legality tests and fixed some bugs. --- tests/hlvariants/chessgamestatetest.cpp | 4 + tests/hlvariants/chesslegalitytest.cpp | 146 ++++++++++++++++++++++- tests/hlvariants/chesslegalitytest.h | 19 +++ tests/hlvariants/chessmovetest.cpp | 4 + tests/hlvariants/prototype/chess/legalitycheck.h | 54 ++++++--- tests/hlvariants/prototype/chess/move.cpp | 3 +- 6 files changed, 204 insertions(+), 26 deletions(-) diff --git a/tests/hlvariants/chessgamestatetest.cpp b/tests/hlvariants/chessgamestatetest.cpp index 0802379..05814d9 100644 --- a/tests/hlvariants/chessgamestatetest.cpp +++ b/tests/hlvariants/chessgamestatetest.cpp @@ -58,6 +58,8 @@ void ChessGameStateTest::test_en_passant() { d5.setType(ChessMove::EN_PASSANT_TRIGGER); m_state->move(d5); + CPPUNIT_ASSERT(m_state->enPassant() == Point(3, 2)); + ChessMove exd6(Point(4, 3), Point(3, 2)); exd6.setType(ChessMove::EN_PASSANT_CAPTURE); m_state->move(exd6); @@ -98,3 +100,5 @@ void ChessGameStateTest::test_promotion() { CPPUNIT_ASSERT(m_state->board().get(Point(7, 0)) == ChessPiece(ChessPiece::WHITE, ChessPiece::BISHOP)); } + + diff --git a/tests/hlvariants/chesslegalitytest.cpp b/tests/hlvariants/chesslegalitytest.cpp index 9d26352..f4b1382 100644 --- a/tests/hlvariants/chesslegalitytest.cpp +++ b/tests/hlvariants/chesslegalitytest.cpp @@ -15,23 +15,157 @@ void ChessLegalityTest::tearDown() { delete m_legality_check; } +void ChessLegalityTest::test_movements() { + ChessMove e4(Point(4, 6), Point(4, 4)); + CPPUNIT_ASSERT_EQUAL(ChessMove::EN_PASSANT_TRIGGER, + m_legality_check->getMoveType( + m_state->board().get(Point(4, 6)), e4)); + + ChessMove crazy(Point(0, 0), Point(7, 4)); + CPPUNIT_ASSERT_EQUAL(ChessMove::INVALID, + m_legality_check->getMoveType( + m_state->board().get(Point(0, 0)), crazy)); +} + +void ChessLegalityTest::test_pseudolegal() { + ChessMove e4(Point(4, 6), Point(4, 4)); + CPPUNIT_ASSERT(m_legality_check->pseudolegal(e4)); + + ChessMove e5(Point(4, 6), Point(4, 3)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(e5)); + + ChessMove Nf3(Point(6, 7), Point(5, 5)); + CPPUNIT_ASSERT(m_legality_check->pseudolegal(Nf3)); + + ChessMove Bc4(Point(5, 7), Point(2, 4)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(Bc4)); + + // black moves + m_state->switchTurn(); + + ChessMove crazy(Point(0, 0), Point(4, 7)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(crazy)); + + ChessMove e5_(Point(4, 1), Point(4, 3)); + CPPUNIT_ASSERT(m_legality_check->pseudolegal(e5_)); +} + void ChessLegalityTest::test_simple_move() { ChessMove e4(Point(4, 6), Point(4, 4)); CPPUNIT_ASSERT(m_legality_check->legal(e4)); - ChessMove e3(Point(4, 6), Point(4, 3)); - CPPUNIT_ASSERT(!m_legality_check->legal(e3)); + ChessMove e5(Point(4, 6), Point(4, 3)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(e5)); ChessMove Nf3(Point(6, 7), Point(5, 5)); CPPUNIT_ASSERT(m_legality_check->legal(Nf3)); ChessMove Bc4(Point(5, 7), Point(2, 4)); - CPPUNIT_ASSERT(!m_legality_check->legal(Bc4)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(Bc4)); + + { + ChessMove tmp(Point(5, 7), Point(2, 4)); + m_state->board().set(Point(4, 6), ChessPiece()); + CPPUNIT_ASSERT(m_legality_check->legal(tmp)); + } + + ChessMove e6(Point(4, 1), Point(4, 2)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(e6)); + + { + ChessMove tmp(Point(4, 1), Point(4, 2)); + m_state->switchTurn(); + CPPUNIT_ASSERT(m_legality_check->legal(tmp)); + } +} + +void ChessLegalityTest::test_promotion() { + m_state->board().set(Point(7, 1), ChessPiece(ChessPiece::WHITE, ChessPiece::PAWN)); + ChessMove h8Q(Point(7, 1), Point(7, 0), ChessPiece::QUEEN); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(h8Q)); + + ChessMove hxg8R(Point(7, 1), Point(6, 0), ChessPiece::ROOK); + CPPUNIT_ASSERT(m_legality_check->pseudolegal(hxg8R)); + CPPUNIT_ASSERT(m_legality_check->legal(hxg8R)); + CPPUNIT_ASSERT_EQUAL((int)ChessPiece::ROOK, hxg8R.promoteTo()); +} + +void ChessLegalityTest::test_en_passant() { + m_state->move(ChessMove(Point(4, 6), Point(4, 4))); + m_state->move(ChessMove(Point(7, 1), Point(7, 2))); + m_state->move(ChessMove(Point(4, 4), Point(4, 3))); + + ChessMove d5(Point(3, 1), Point(3, 3)); + CPPUNIT_ASSERT(m_legality_check->legal(d5)); + CPPUNIT_ASSERT(d5.enPassantTrigger() == Point(3, 2)); + m_state->move(d5); + + ChessMove exd6(Point(4, 3), Point(3, 2)); + CPPUNIT_ASSERT(m_legality_check->legal(exd6)); + CPPUNIT_ASSERT(exd6.captureSquare() == Point(3, 3)); + + m_state->move(ChessMove(Point(7, 6), Point(7, 5))); + m_state->move(ChessMove(Point(7, 2), Point(7, 3))); + + ChessMove tmp(Point(4, 3), Point(3, 2)); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(tmp)); +} + +void ChessLegalityTest::test_castling() { + ChessMove oo(Point(4, 7), Point(6, 7)); + + m_state->board().set(Point(6, 7), ChessPiece()); + { + ChessMove tmp(oo); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(tmp)); + } + + m_state->board().set(Point(5, 7), ChessPiece()); + { + ChessMove tmp(oo); + CPPUNIT_ASSERT(m_legality_check->legal(tmp)); + } - ChessMove tmp(Point(5, 7), Point(2, 4)); - m_state->board().set(Point(4, 6), ChessPiece()); - CPPUNIT_ASSERT(m_legality_check->legal(tmp)); + m_state->board().set(Point(3, 6), ChessPiece(ChessPiece::BLACK, ChessPiece::PAWN)); + { + ChessMove tmp(oo); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(tmp)); + } + + m_state->board().set(Point(3, 6), ChessPiece()); + m_state->board().set(Point(4, 6), ChessPiece(ChessPiece::BLACK, ChessPiece::PAWN)); + { + ChessMove tmp(oo); + CPPUNIT_ASSERT(!m_legality_check->pseudolegal(tmp)); + } +} + +void ChessLegalityTest::test_attack1() { + m_state->board().set(Point(5, 5), ChessPiece(ChessPiece::BLACK, ChessPiece::ROOK)); + CPPUNIT_ASSERT(m_legality_check->attacks(ChessPiece::WHITE, Point(5, 5))); +} + +void ChessLegalityTest::test_attack2() { + m_state->board().set(Point(4, 4), ChessPiece(ChessPiece::BLACK, ChessPiece::QUEEN)); + CPPUNIT_ASSERT(!m_legality_check->attacks(ChessPiece::WHITE, Point(4, 4))); } +void ChessLegalityTest::test_attack3() { + m_state->board().set(Point(0, 5), ChessPiece(ChessPiece::BLACK, ChessPiece::KING)); + m_state->board().set(Point(1, 6), ChessPiece(ChessPiece::WHITE, ChessPiece::ROOK)); // b2: pawn -> rook + CPPUNIT_ASSERT(m_legality_check->attacks(ChessPiece::WHITE, Point(0, 5))); + + m_state->board().set(Point(1, 7), ChessPiece()); // remove knight on b1 + CPPUNIT_ASSERT(!m_legality_check->attacks(ChessPiece::WHITE, Point(0, 5))); + + m_state->board().set(Point(0, 6), ChessPiece()); // remove pawn on a2 + CPPUNIT_ASSERT(m_legality_check->attacks(ChessPiece::WHITE, Point(0, 5))); + + m_state->board().set(Point(0, 7), ChessPiece()); // remove rook on a1 + CPPUNIT_ASSERT(!m_legality_check->attacks(ChessPiece::WHITE, Point(0, 5))); +} +void ChessLegalityTest::test_attack4() { + CPPUNIT_ASSERT(!m_legality_check->attacks(ChessPiece::BLACK, Point(4, 7))); +} diff --git a/tests/hlvariants/chesslegalitytest.h b/tests/hlvariants/chesslegalitytest.h index 16f4153..56801eb 100644 --- a/tests/hlvariants/chesslegalitytest.h +++ b/tests/hlvariants/chesslegalitytest.h @@ -27,7 +27,16 @@ typedef HLVariant::Chess::LegalityCheck ChessLegalityCheck; class ChessLegalityTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ChessLegalityTest); + CPPUNIT_TEST(test_movements); + CPPUNIT_TEST(test_pseudolegal); CPPUNIT_TEST(test_simple_move); + CPPUNIT_TEST(test_promotion); + CPPUNIT_TEST(test_en_passant); + CPPUNIT_TEST(test_castling); + CPPUNIT_TEST(test_attack1); + CPPUNIT_TEST(test_attack2); + CPPUNIT_TEST(test_attack3); + CPPUNIT_TEST(test_attack4); CPPUNIT_TEST_SUITE_END(); private: ChessGameState* m_state; @@ -36,8 +45,18 @@ public: void setUp(); void tearDown(); + void test_movements(); + void test_pseudolegal(); void test_simple_move(); + void test_promotion(); + void test_en_passant(); + void test_castling(); + void test_attack1(); + void test_attack2(); + void test_attack3(); + void test_attack4(); }; #endif // CHESSGAMESTATETEST_H + diff --git a/tests/hlvariants/chessmovetest.cpp b/tests/hlvariants/chessmovetest.cpp index c05f24a..3334623 100644 --- a/tests/hlvariants/chessmovetest.cpp +++ b/tests/hlvariants/chessmovetest.cpp @@ -22,6 +22,10 @@ void ChessMoveTest::test_en_passant_trigger() { ChessMove m(Point(4, 6), Point(4, 4)); m.setType(ChessMove::EN_PASSANT_TRIGGER); CPPUNIT_ASSERT(m.enPassantTrigger() == Point(4, 5)); + + ChessMove m2(Point(3, 1), Point(3, 3)); + m2.setType(ChessMove::EN_PASSANT_TRIGGER); + CPPUNIT_ASSERT(m2.enPassantTrigger() == Point(3, 2)); } void ChessMoveTest::test_promotion() { diff --git a/tests/hlvariants/prototype/chess/legalitycheck.h b/tests/hlvariants/prototype/chess/legalitycheck.h index 10aa41d..1cd1519 100644 --- a/tests/hlvariants/prototype/chess/legalitycheck.h +++ b/tests/hlvariants/prototype/chess/legalitycheck.h @@ -19,10 +19,16 @@ public: LegalityCheck(const GameState& state); virtual ~LegalityCheck(); - virtual typename Move::Type getMoveType(const Piece& piece, const Move& move) const; + virtual typename Move::Type getMoveType( + const Piece& piece, + const Move& move, + const Piece& target = Piece()) const; virtual bool pseudolegal(Move& move) const; virtual bool legal(Move& move) const; - virtual bool attacks(typename Piece::Color color, const Point& p) const; + virtual bool attacks( + typename Piece::Color color, + const Point& p, + const Piece& target = Piece()) const; virtual bool checkPromotion(typename Piece::Type type) const; }; @@ -82,12 +88,12 @@ bool LegalityCheck::pseudolegal(Move& move) const { return false; if (move.kingSideCastling()) { if (attacks(otherTurn, move.from()) || - attacks(otherTurn, move.from() + Point(1, 0))) + attacks(otherTurn, move.from() + Point(1, 0), piece)) return false; } if (move.queenSideCastling()) { if (attacks(otherTurn, move.from()) || - attacks(otherTurn, move.from() + Point(-1, 0))) + attacks(otherTurn, move.from() + Point(-1, 0), piece)) return false; } @@ -99,7 +105,11 @@ bool LegalityCheck::pseudolegal(Move& move) const { } template -typename GameState::Move::Type LegalityCheck::getMoveType(const Piece& piece, const Move& move) const { +typename GameState::Move::Type +LegalityCheck:: +getMoveType(const Piece& piece, const Move& move, const Piece& _target) const { + Piece target = _target == Piece() ? m_state.board().get(move.to()) : _target; + switch (piece.type()) { case Piece::ROOK: @@ -107,8 +117,7 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece if (move.from() == move.to()) return Move::INVALID; PathInfo path = m_state.board().path(move.from(), move.to()); - if (path.parallel() && path.clear() && - m_state.board().get(move.to()).color() != piece.color()) + if (path.parallel() && path.clear() && target.color() != piece.color()) return Move::NORMAL; else return Move::INVALID; @@ -119,15 +128,14 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece if (move.from() == move.to()) return Move::INVALID; PathInfo path = m_state.board().path(move.from(), move.to()); - if (path.diagonal() && path.clear() && - m_state.board().get(move.to()).color() != piece.color()) + if (path.diagonal() && path.clear() && target.color() != piece.color()) return Move::NORMAL; else return Move::INVALID; } case Piece::KNIGHT: - if (m_state.board().get(move.to()).color() == piece.color()) + if (target.color() == piece.color()) return Move::INVALID; else { @@ -144,8 +152,7 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece if (move.from() == move.to()) return Move::INVALID; PathInfo path = m_state.board().path(move.from(), move.to()); - if (path.valid() && path.clear() && - m_state.board().get(move.to()).color() != piece.color()) + if (path.valid() && path.clear() && target.color() != piece.color()) return Move::NORMAL; else return Move::INVALID; @@ -156,9 +163,9 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece if (move.from() == move.to()) return Move::INVALID; Point delta = move.to() - move.from(); - if (abs(delta.x) <= 1 && abs(delta.y) <= 1 && - m_state.board().get(move.to()).color() != piece.color()) + if (abs(delta.x) <= 1 && abs(delta.y) <= 1 && target.color() != piece.color()) { return Move::NORMAL; + } else if (move.from() == m_state.kingStartingPosition(piece.color())) { if (delta == Point(2,0)) { if (m_state.board().get(move.from() + Point(1,0)) == Piece() && @@ -168,7 +175,7 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece } else if (delta == Point(-2,0)) { if (m_state.board().get(move.from() - Point(1, 0)) == Piece() && - m_state.board().get(move.from() - Point(2, 0)) == Piece() && + m_state.board().get(move.to() + Point(1, 0)) == Piece() && m_state.board().get(move.to()) == Piece() && m_state.queenCastling(piece.color())) return Move::QUEEN_SIDE_CASTLING; @@ -179,12 +186,11 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece case Piece::PAWN: { - Piece destinationPiece = m_state.board().get(move.to()); Point delta = move.to() - move.from(); bool enPassant = m_state.enPassant() == move.to(); // moving - if (destinationPiece == Piece() && !enPassant) { + if (target == Piece() && !enPassant) { if (delta == m_state.direction(piece.color())) { if (move.to().y == m_state.promotionRank(piece.color())) return Move::PROMOTION; @@ -202,7 +208,7 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece } // capturing - else if (enPassant || destinationPiece.color() != piece.color()) { + else if (enPassant || target.color() != piece.color()) { if (delta.y == m_state.direction(piece.color()).y && abs(delta.x) == 1) { if (enPassant) @@ -223,7 +229,17 @@ typename GameState::Move::Type LegalityCheck::getMoveType(const Piece } template -bool LegalityCheck::attacks(typename Piece::Color, const Point&) const { +bool LegalityCheck::attacks(typename Piece::Color color, const Point& to, const Piece& target) const { + for (int i = 0; i < m_state.board().size().x; i++) { + for (int j = 0; j < m_state.board().size().y; j++) { + Point p(i, j); + Piece piece = m_state.board().get(p); + Move move(p, to); + if (piece != Piece() && piece.color() == color + && getMoveType(piece, move, target) != Move::INVALID) + return true; + } + } return false; } diff --git a/tests/hlvariants/prototype/chess/move.cpp b/tests/hlvariants/prototype/chess/move.cpp index 629cb85..10de657 100644 --- a/tests/hlvariants/prototype/chess/move.cpp +++ b/tests/hlvariants/prototype/chess/move.cpp @@ -4,7 +4,8 @@ namespace HLVariant { namespace Chess { Move::Move(const Point& from, const Point& to, int promotionType) -: m_from(from) +: m_type(NORMAL) +, m_from(from) , m_to(to) , m_promotion(promotionType) { } -- 2.11.4.GIT