-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhashtable.cpp
More file actions
162 lines (130 loc) · 4.22 KB
/
hashtable.cpp
File metadata and controls
162 lines (130 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "position.h"
#include "hashtable.h"
#include "search.h"
/////////////////////////////////////
// TRANSPOSITION TABLE AND HASHING //
/////////////////////////////////////
// random piece keys [piece][square]
uint64_t piece_keys[13][64];
// random enpassant keys [square]
uint64_t enpassant_keys[64];
// random castling keys
uint64_t castle_keys[16];
// random side key
uint64_t side_key;
// transition table structure
struct tt {
uint64_t key; // hash key
int depth; // search depth
int flag; // type of node (pv, alpha, or beta)
int score; // score (exact, alpha, or beta)
//int best_move;
};
// init hashtable size to 8 MB
const int hash_table_size = 20 * 1024 * 1024 / sizeof(tt);
tt hash_table[hash_table_size];
uint64_t state = 0x536ABC791996ULL; /* The state must be seeded with a nonzero value. */
/* xorshift64* https://en.wikipedia.org/wiki/Xorshift
generate pseudo random 64bit number*/
uint64_t get_random_U64_number() {
uint64_t x = state;
x ^= x >> 12; // a
x ^= x << 25; // b
x ^= x >> 27; // c
state = x;
return x * 0x2545F4914F6CDD1DULL;
}
void init_random_keys() {
// loop over piece codes
for (int piece = p; piece <= K; piece++) {
// loop over squares
for (int square = 0; square < 64; square++) {
// init random piece keys
piece_keys[piece][square] = get_random_U64_number();
}
}
// loop over squares
for (int square = 0; square < 64; square++) {
// init random enpassant keys
enpassant_keys[square] = get_random_U64_number();
}
// init random side key
side_key = get_random_U64_number();
// loop over castling keys
for (int index = 0; index < 16; index++) {
// init castle random keys
castle_keys[index] = get_random_U64_number();
}
}
// generate "almost unique" position ID aka hash key from scratch
uint64_t generate_hash_key(Position &pos) {
// final hash key
uint64_t final_key = 0;
// loop over squares
for (int rank = 0; rank < 8; rank++) {
for (int file = 0; file < 8; file++) {
// square as 0..127
int square = rank * 16 + file;
// square as 0..63
int square_in_64 = rank * 8 + file;
int piece = pos.board[square];
if (!(square & 0x88) && piece != e) {
final_key ^= piece_keys[piece][square_in_64];
}
}
}
// if enpassant square is on board
if (pos.enpassant != no_sq) {
// hash enpassant
int square = pos.enpassant;
int square_in_64 = (square >> 4) * 8 + (square & 7);
final_key ^= enpassant_keys[square_in_64];
}
// hash castling rights
final_key ^= castle_keys[pos.castle];
// hash side to move only on black to move
if (pos.side == black) {
final_key ^= side_key;
}
// return final key
return final_key;
}
// reset the hash table
void clear_hash_table() {
for (tt &entry : hash_table) {
entry.key = 0;
entry.depth = 0;
entry.flag = 0;
entry.score = 0;
}
}
// probe the hash table
int read_hash_entry(uint64_t hash_key, int alpha, int beta, int depth) {
tt *hash_entry = &hash_table[hash_key % hash_table_size];
if (hash_entry->key == hash_key) {
if (hash_entry->depth >= depth) {
int score = hash_entry->score;
if (score < -mate_score) score += ply;
if (score > mate_score) score -= ply;
if (hash_entry->flag == hash_flag_exact)
return score;
if (hash_entry->flag == hash_flag_alpha)
if (score <= alpha)
return alpha;
if (hash_entry->flag == hash_flag_beta)
if (score >= beta)
return beta;
}
}
return no_hash_entry;
}
// write in the hash table
void write_hash_entry(uint64_t hash_key, int score, int depth, int hash_flag) {
tt *hash_entry = &hash_table[hash_key % hash_table_size];
if (score < -mate_score) score -= ply;
if (score > mate_score) score += ply;
hash_entry->key = hash_key;
hash_entry->score = score;
hash_entry->depth = depth;
hash_entry->flag = hash_flag;
}