Remove 'get_' from HashTable getters
[purplehaze.git] / test / unit / test_transpositions.cpp
blobec9f01f685e7ed87e05df86a981be0f61504c2c4
1 #include <climits>
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
15 EXPECT_EQ(6, size);
16 EXPECT_EQ(size, sizeof(Transposition));
19 TEST(TranspositionTest, Constructor)
21 Transposition t1;
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));
45 EXPECT_EQ(t3, t2);
46 EXPECT_NE(t4, t2);
47 EXPECT_NE(t5, t2);
48 EXPECT_NE(t6, t2);
49 EXPECT_NE(t7, t2);
55 class TranspositionsTest : public testing::Test
57 protected:
58 Transpositions tt;
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)
85 tt.clear();
86 int n = tt.size();
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)
95 tt.clear();
96 int n = tt.size();
97 for (int i = 0; i < n; ++i) {
98 Hash h = hash_from_index(i);
99 bool is_empty;
100 Transposition trans = tt.lookup(h, &is_empty);
101 if (i == 0) {
102 // FIXME
103 EXPECT_FALSE(is_empty);
104 EXPECT_EQ(UNDEF_BOUND, trans.get_bound());
105 } else {
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) {
113 if (++i >= n) break;
114 // Create transposition
115 Move m(E2, E4, QUIET_MOVE);
116 int v = s + i;
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) {
135 if (++i >= n) break;
136 // Create transposition
137 Move m(E2, E4, QUIET_MOVE);
138 int v = s + i;
139 Hash h = hash_from_index(i);
140 Transposition trans_sent(v, b, d, m);
142 // Lookup transposition
143 bool is_empty;
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)
158 Game game;
159 game.tt.clear();
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));
168 bool is_empty;
169 Position &pos = game.current_position();
170 Move m2 = game.tt.lookup(pos.hash(), &is_empty).get_best_move();
171 EXPECT_EQ(m1, m2);