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
.get_value());
24 EXPECT_EQ(0, t1
.get_depth());
25 EXPECT_EQ(Move(), t1
.get_best_move());
26 EXPECT_EQ(UNDEF_BOUND
, t1
.get_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
.get_value());
35 EXPECT_EQ(d
, t2
.get_depth());
36 EXPECT_EQ(m
, t2
.get_best_move());
37 EXPECT_EQ(b
, t2
.get_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 // But internal array entries number should be a power of two
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
, Lookup
)
97 for (int i
= 0; i
< n
; ++i
) {
98 Hash h
= hash_from_index(i
);
100 Transposition trans
= tt
.lookup(h
, &is_empty
);
103 EXPECT_FALSE(is_empty
);
104 EXPECT_EQ(UNDEF_BOUND
, trans
.get_bound());
106 EXPECT_TRUE(is_empty
);
109 for (int i
= -1; i
< n
; ++i
) {
110 for (int s
= SHRT_MIN
; s
<= SHRT_MAX
; s
+= 1000) {
111 for (int d
= 0; d
<= UCHAR_MAX
; ++d
) {
112 for (const Bound
&b
: BOUNDS
) {
114 // Create transposition
115 Move
m(E2
, E4
, QUIET_MOVE
);
117 Hash h
= hash_from_index(i
);
118 Transposition
trans_sent(v
, b
, d
, m
);
120 // Save transposition
121 tt
.save(h
, v
, b
, d
, m
);
123 // Check transposition
124 EXPECT_FALSE(tt
.value_at(i
).is_empty());
125 EXPECT_EQ(trans_sent
, tt
.value_at(i
));
126 EXPECT_EQ(h
, tt
.hash_at(i
));
131 for (int i
= -1; i
< n
; ++i
) {
132 for (int s
= SHRT_MIN
; s
<= SHRT_MAX
; s
+= 1000) {
133 for (int d
= 0; d
<= UCHAR_MAX
; ++d
) {
134 for (const Bound
&b
: BOUNDS
) {
136 // Create transposition
137 Move
m(E2
, E4
, QUIET_MOVE
);
139 Hash h
= hash_from_index(i
);
140 Transposition
trans_sent(v
, b
, d
, m
);
142 // Lookup transposition
144 Transposition trans_received
= tt
.lookup(h
, &is_empty
);
145 EXPECT_FALSE(is_empty
);
146 EXPECT_EQ(trans_sent
, trans_received
);
154 * Test case for retrieving the best move from TT after a search
156 TEST(TTTest
, LookupAfterSearch
)
160 game
.clear_killers();
161 game
.search_moves
.clear();
163 game
.init("7K/8/k1P5/7p/8/8/8/8 w - -");
164 game
.time
= Time(1, 50); // Search 1 move in 50 ms
165 Move m1
= game
.root(MAX_PLY
);
166 EXPECT_EQ("Kg7", game
.output_move(m1
));
169 Position
&pos
= game
.current_position();
170 Move m2
= game
.tt
.lookup(pos
.hash(), &is_empty
).get_best_move();