Refactor move generation
[purplehaze.git] / test / unit / test_move.cpp
bloba87ebaf4aebd0a681b12c1efc3ecc1e29c645b9a
1 #include <algorithm>
2 #include <climits>
4 #include "../../src/move.h"
5 #include "../../src/board.h"
6 #include "gtest/gtest.h"
8 // Helper template returning the size of a one dimension array at compile time
9 template<typename T, size_t N>
10 constexpr size_t array_size(const T (&)[N])
12 return N;
15 static const MoveType MOVES[] = {
16 QUIET_MOVE,
17 DOUBLE_PAWN_PUSH,
18 KING_CASTLE,
19 QUEEN_CASTLE,
20 CAPTURE,
21 EN_PASSANT,
22 NULL_MOVE,
23 KNIGHT_PROMOTION,
24 BISHOP_PROMOTION,
25 ROOK_PROMOTION,
26 QUEEN_PROMOTION,
27 KNIGHT_PROMOTION_CAPTURE,
28 BISHOP_PROMOTION_CAPTURE,
29 ROOK_PROMOTION_CAPTURE,
30 QUEEN_PROMOTION_CAPTURE
33 static const MoveType PROMOTIONS[] = {
34 KNIGHT_PROMOTION,
35 BISHOP_PROMOTION,
36 ROOK_PROMOTION,
37 QUEEN_PROMOTION,
38 KNIGHT_PROMOTION_CAPTURE,
39 BISHOP_PROMOTION_CAPTURE,
40 ROOK_PROMOTION_CAPTURE,
41 QUEEN_PROMOTION_CAPTURE
43 static const int NB_PROMOTIONS = array_size(PROMOTIONS);
45 static const MoveType CAPTURES[] = {
46 CAPTURE,
47 EN_PASSANT,
48 KNIGHT_PROMOTION_CAPTURE,
49 BISHOP_PROMOTION_CAPTURE,
50 ROOK_PROMOTION_CAPTURE,
51 QUEEN_PROMOTION_CAPTURE
53 static const int NB_CAPTURES = array_size(CAPTURES);
55 TEST(MoveTest, Size)
57 EXPECT_EQ(2, sizeof(uint16_t));
58 EXPECT_EQ(sizeof(uint16_t), sizeof(Move));
61 TEST(MoveTest, Constructor)
63 Move null_move;
64 EXPECT_TRUE(null_move.is_null());
65 EXPECT_TRUE(Move().is_null());
67 for (const Square &o : SQUARES) {
68 if (o == OUT) continue;
69 for (const Square &d : SQUARES) {
70 if (d == OUT || d == o) continue;
71 for (const MoveType &t : MOVES) {
72 Move m(o, d, t);
73 EXPECT_EQ(o, m.orig());
74 EXPECT_EQ(d, m.dest());
75 EXPECT_EQ(t, m.type());
77 EXPECT_EQ(Board::file(o), m.orig_file());
78 EXPECT_EQ(Board::file(d), m.dest_file());
79 EXPECT_EQ(Board::rank(o), m.orig_rank());
80 EXPECT_EQ(Board::rank(d), m.dest_rank());
83 // FIXME: Takes too long, too much moves
84 for (const Square &o2 : SQUARES) {
85 if (o2 == OUT) continue;
86 for (const Square &d2 : SQUARES) {
87 if (d2 == OUT || d2 == o2) continue;
88 for (const MoveType &t2 : MOVES) {
89 Move m2(o2, d2, t2);
90 if (o == o2 && d == d2 && t == t2) {
91 EXPECT_EQ(m2, m);
92 } else {
93 EXPECT_NE(m2, m);
104 TEST(MoveTest, Type)
106 for (const MoveType &t : MOVES) {
107 // Define move types
108 bool is_null = t == NULL_MOVE;
109 bool is_en_passant = t == EN_PASSANT;
110 bool is_double_pawn_push = t == DOUBLE_PAWN_PUSH;
111 bool is_castle = t == KING_CASTLE || t == QUEEN_CASTLE;
112 bool is_capture =
113 std::binary_search(CAPTURES, CAPTURES + NB_CAPTURES, t);
114 bool is_promotion =
115 std::binary_search(PROMOTIONS, PROMOTIONS + NB_PROMOTIONS, t);
117 for (const Square &o : SQUARES) {
118 if (o == OUT) continue;
119 for (const Square &d : SQUARES) {
120 if (d == OUT || d == o) continue;
121 Move m(o, d, t);
122 EXPECT_EQ(is_null, m.is_null());
123 EXPECT_EQ(is_en_passant, m.is_en_passant());
124 EXPECT_EQ(is_double_pawn_push, m.is_double_pawn_push());
125 EXPECT_EQ(is_castle, m.is_castle());
126 EXPECT_EQ(is_capture, m.is_capture());
127 EXPECT_EQ(is_promotion, m.is_promotion());
129 switch (t) {
130 case KING_CASTLE:
131 EXPECT_EQ(KING, m.castle_side());
132 break;
133 case QUEEN_CASTLE:
134 EXPECT_EQ(QUEEN, m.castle_side());
135 break;
136 case KNIGHT_PROMOTION:
137 case KNIGHT_PROMOTION_CAPTURE:
138 EXPECT_EQ(KNIGHT, m.promotion_type());
139 break;
140 case BISHOP_PROMOTION:
141 case BISHOP_PROMOTION_CAPTURE:
142 EXPECT_EQ(BISHOP, m.promotion_type());
143 break;
144 case ROOK_PROMOTION:
145 case ROOK_PROMOTION_CAPTURE:
146 EXPECT_EQ(ROOK, m.promotion_type());
147 break;
148 case QUEEN_PROMOTION:
149 case QUEEN_PROMOTION_CAPTURE:
150 EXPECT_EQ(QUEEN, m.promotion_type());
151 break;
152 default:
153 break;
161 TEST(ExtendedMoveTest, Size)
163 int size = sizeof(uint16_t) + sizeof(char) + 1; // 1 byte of padding
164 EXPECT_EQ(4, size);
165 EXPECT_EQ(size, sizeof(ExtendedMove));
168 TEST(ExtendedMoveTest, Constructor)
170 EXPECT_EQ(Move(), ExtendedMove());
171 EXPECT_EQ(0, ExtendedMove().value());
173 for (const Square &o : SQUARES) {
174 if (o == OUT) continue;
175 for (const Square &d : SQUARES) {
176 if (d == OUT || d == o) continue;
177 for (const MoveType &t : MOVES) {
178 Move m(o, d, t);
179 ExtendedMove em1(m);
180 ExtendedMove em2(m, 0);
181 EXPECT_EQ(m, em1);
182 EXPECT_EQ(em1, em2);
184 // '==' and '!=' operators are inherited from Move class
185 ExtendedMove em3(m, 50);
186 EXPECT_EQ(em2, em3);
192 TEST(ExtendedMoveTest, Score)
194 Move m;
195 for (int i = SCHAR_MIN; i <= SCHAR_MAX; ++i) {
196 ExtendedMove em1(m, i);
197 EXPECT_EQ(i, em1.value());
199 // Test getter and setter
200 ExtendedMove em2(m, 0);
201 EXPECT_EQ(0, em2.value());
205 TEST(ExtendedMoveTest, Comp)
207 Move m;
208 ExtendedMove em1(m, 0);
209 ExtendedMove em2(m, SCHAR_MAX);
210 for (int i = SCHAR_MIN; i <= SCHAR_MAX; ++i) {
211 ExtendedMove em3(m, i);
212 EXPECT_EQ(i < 0, em1 < em3);
213 if (i < 0) {
214 EXPECT_LT(em1, em3);
216 if (i < SCHAR_MAX) {
217 EXPECT_LT(em2, em3);