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