3 #include "../../src/tt.h"
4 #include "../../src/game.h"
5 #include "gtest/gtest.h"
7 static const Bound BOUNDS
[] = { EXACT
, LOWER
, UPPER
};
9 TEST(TranspositionTest
, Size
)
11 int size
= sizeof(int16_t) + // 2 bytes
12 sizeof(Move
) + // 2 bytes
13 sizeof(unsigned char) + // 1 byte
14 sizeof(Bound
); // 1 byte
16 EXPECT_EQ(size
, sizeof(Transposition
));
19 TEST(TranspositionTest
, Constructor
)
22 EXPECT_TRUE(t1
.is_empty());
23 EXPECT_EQ(0, t1
.value());
24 EXPECT_EQ(0, t1
.depth());
25 EXPECT_EQ(Move(), t1
.best_move());
26 EXPECT_EQ(UNDEF_BOUND
, t1
.bound());
28 for (int v
= SHRT_MIN
; v
<= SHRT_MAX
; v
+= 1000) {
29 for (int d
= 0; d
<= UCHAR_MAX
; ++d
) {
30 for (const Bound
&b
: BOUNDS
) {
31 Move
m(E2
, E3
, QUIET_MOVE
);
32 Transposition
t2(v
, b
, d
, m
);
33 EXPECT_FALSE(t2
.is_empty());
34 EXPECT_EQ(v
, t2
.value());
35 EXPECT_EQ(d
, t2
.depth());
36 EXPECT_EQ(m
, t2
.best_move());
37 EXPECT_EQ(b
, t2
.bound());
39 Transposition
t3(v
, b
, d
, m
);
40 Transposition
t4(v
+ 1, b
, d
, m
);
41 Transposition
t5(v
, UNDEF_BOUND
, d
, m
);
42 Transposition
t6(v
, b
, d
+ 1, m
);
43 Transposition
t7(v
, b
, d
, Move(F2
, F3
, QUIET_MOVE
));
55 class TranspositionsTest
: public testing::Test
60 Hash
hash_from_index(int i
) const {
61 return static_cast<Hash
>(i
& (tt
.size() - 1));
65 TEST_F(TranspositionsTest
, Size
)
67 HashTable
<Transposition
> ht(TT_SIZE
);
68 EXPECT_EQ(sizeof(ht
), sizeof(tt
));
69 int entry_size
= sizeof(Hash
) + // 8 bytes
70 sizeof(Transposition
) + // 6 bytes
71 2; // 2 bytes (padding)
72 int size
= TT_SIZE
/ entry_size
;
74 // TODO Internal array size should not be a power of two?
75 //EXPECT_NE(0, TT_SIZE & (TT_SIZE - 1));
77 // 'size' must be a power of two for Transpositions::lookup()
78 EXPECT_EQ(0, size
& (size
- 1));
80 EXPECT_EQ(size
, tt
.size());
83 TEST_F(TranspositionsTest
, Constructor
)
87 for (int i
= 0; i
< n
; ++i
) {
88 EXPECT_TRUE(tt
.value_at(i
).is_empty());
89 EXPECT_EQ(0, tt
.hash_at(i
));
93 TEST_F(TranspositionsTest
, ConstructorWithoutClear
)
96 for (int i
= 0; i
< n
; ++i
) {
97 EXPECT_TRUE(tt
.value_at(i
).is_empty());
98 EXPECT_EQ(0, tt
.hash_at(i
));
102 TEST_F(TranspositionsTest
, Lookup
)
106 for (int i
= 0; i
< n
; ++i
) {
107 Hash h
= hash_from_index(i
);
109 Transposition trans
= tt
.lookup(h
, &is_empty
);
112 EXPECT_FALSE(is_empty
);
113 EXPECT_EQ(UNDEF_BOUND
, trans
.bound());
115 EXPECT_TRUE(is_empty
);
118 for (int i
= -1; i
< n
; ++i
) {
119 for (int s
= SHRT_MIN
; s
<= SHRT_MAX
; s
+= 1000) {
120 for (int d
= 0; d
<= UCHAR_MAX
; ++d
) {
121 for (const Bound
&b
: BOUNDS
) {
123 // Create transposition
124 Move
m(E2
, E4
, QUIET_MOVE
);
126 Hash h
= hash_from_index(i
);
127 Transposition
trans_sent(v
, b
, d
, m
);
129 // Save transposition
130 tt
.save(h
, v
, b
, d
, m
);
132 // Check transposition
133 EXPECT_FALSE(tt
.value_at(i
).is_empty());
134 EXPECT_EQ(trans_sent
, tt
.value_at(i
));
135 EXPECT_EQ(h
, tt
.hash_at(i
));
140 for (int i
= -1; i
< n
; ++i
) {
141 for (int s
= SHRT_MIN
; s
<= SHRT_MAX
; s
+= 1000) {
142 for (int d
= 0; d
<= UCHAR_MAX
; ++d
) {
143 for (const Bound
&b
: BOUNDS
) {
145 // Create transposition
146 Move
m(E2
, E4
, QUIET_MOVE
);
148 Hash h
= hash_from_index(i
);
149 Transposition
trans_sent(v
, b
, d
, m
);
151 // Lookup transposition
153 Transposition trans_received
= tt
.lookup(h
, &is_empty
);
154 EXPECT_FALSE(is_empty
);
155 EXPECT_EQ(trans_sent
, trans_received
);
163 * Test case for retrieving the best move from TT after a search
165 TEST(TTTest
, LookupAfterSearch
)
169 game
.clear_killers();
170 game
.search_moves
.clear();
172 game
.init("7K/8/k1P5/7p/8/8/8/8 w - -");
173 game
.time
= Time(1, 200); // Search 1 move in 200 ms
174 Move m1
= game
.root(MAX_PLY
);
175 EXPECT_NE("c7", game
.output_move(m1
)); // BM at depth <= 3
176 EXPECT_NE("Kh7", game
.output_move(m1
)); // BM at depth <= 13
177 EXPECT_EQ("Kg7", game
.output_move(m1
)); // BM at depth >= 13
180 Position
&pos
= game
.current_position();
181 Move m2
= game
.tt
.lookup(pos
.hash(), &is_empty
).best_move();