search: fixed a bug in NULL move pruning
[owl.git] / trans.c
blobf49668758705da56da8aae94acf8d8831ca9435f
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #include "common.h"
17 #include "board.h"
18 #include "engine.h"
19 #include "trans.h"
21 uint64_t pawn_hash_mask;
22 uint64_t main_hash_mask;
24 struct pawn_hash_entry_t *pawn_hash[2];
25 struct main_hash_entry_t *main_hash;
27 uint16_t hashtable_age;
29 int
30 initialize_main_hashtable(void)
32 int max_elements;
34 main_hash = 0;
36 if (!e.main_hash_size || !e.main_hash_enabled)
37 return 0;
39 main_hash_mask = 0;
41 max_elements = (e.main_hash_size * 1024 * 1024 / 4) / \
42 sizeof(struct main_hash_entry_t);
44 /* calculate hashmask */
45 while (max_elements >>= 1)
46 main_hash_mask = (main_hash_mask << 1) | 1;
48 /* allocate memory */
49 if (!(main_hash = malloc(4 * (main_hash_mask + 1) * \
50 sizeof(struct main_hash_entry_t))))
51 return -1;
53 #ifdef CONSOLE_DEBUG
54 fprintf(stdout, "Allocated main hashtable: %lluk entries, %lluMB\n",
55 (4 * main_hash_mask) >> 10, (4 * main_hash_mask *
56 sizeof(struct main_hash_entry_t)) >> 20);
57 #endif
59 return 0;
62 int
63 initialize_pawn_hashtable(void)
65 int max_elements;
67 pawn_hash[0] = 0;
68 pawn_hash[1] = 0;
70 if (!e.pawn_hash_size || !e.pawn_hash_enabled)
71 return 0;
73 pawn_hash_mask = 0;
74 pawn_hash[WHITE] = 0;
75 pawn_hash[BLACK] = 0;
77 max_elements = (e.pawn_hash_size * 1024 * 1024 / 2) / \
78 sizeof(struct pawn_hash_entry_t);
80 /* calculate hashmask */
81 while (max_elements >>= 1)
82 pawn_hash_mask = (pawn_hash_mask << 1) | 1;
84 /* allocate memory */
85 if (!(pawn_hash[WHITE] = malloc((pawn_hash_mask + 1) * \
86 sizeof(struct pawn_hash_entry_t))))
87 return -1;
88 if (!(pawn_hash[BLACK] = malloc((pawn_hash_mask + 1) * \
89 sizeof(struct pawn_hash_entry_t)))) {
90 free(pawn_hash[WHITE]);
91 return -1;
94 #ifdef CONSOLE_DEBUG
95 fprintf(stdout, "Allocated pawn hashtable: %lluk entries, %lluMB\n",
96 (2 * pawn_hash_mask) >> 10, (2 * pawn_hash_mask *
97 sizeof(struct pawn_hash_entry_t)) >> 20);
98 #endif
99 return 0;
102 int
103 hashtable_get(int side, int depth, int ply, int *move, int *score)
105 int i;
106 int found;
107 int entry_depth;
108 struct main_hash_entry_t *mhe;
110 found = FALSE;
111 mhe = main_hash + (brd.hash_key & main_hash_mask) * 4;
113 for (i = 0; i < 4; i++, mhe++) {
114 if (mhe->key == brd.hash_key) {
115 found = TRUE;
116 break;
120 if (!found) {
121 *move = 0;
122 return INVALID;
125 entry_depth = (mhe->mdf >> 21) & 0xFF;
126 *move = mhe->mdf & 0x1FFFFF;
128 if (entry_depth < depth)
129 return INVALID;
131 *score = mhe->score;
133 if (SCORE_IS_MATE(*score))
134 *score += *score > 0 ? -ply : ply;
136 return mhe->mdf >> 29;
139 void
140 hashtable_put(int side, int depth, int ply, int flag, int move, int score)
142 int i;
143 int entry_depth;
144 int replace_depth;
145 struct main_hash_entry_t *mhe;
146 struct main_hash_entry_t *replace;
148 mhe = main_hash + (brd.hash_key & main_hash_mask) * 4;
149 replace = mhe;
151 for (i = 0; i < 4; i++, mhe++) {
152 if (mhe->key == brd.hash_key) {
153 mhe->mdf = move | (depth << 21) | (flag << 29);
154 mhe->score = score;
156 if (SCORE_IS_MATE(score))
157 mhe->score += score > 0 ? ply : -ply;
158 return;
161 entry_depth = (mhe->mdf >> 21) & 0xFF;
162 replace_depth = (replace->mdf >> 21) & 0xFF;
164 if (replace->age == hashtable_age) {
165 if (mhe->age != hashtable_age || entry_depth < replace_depth)
166 replace = mhe;
167 } else if (mhe->age != hashtable_age && entry_depth < replace_depth)
168 replace = mhe;
171 replace->key = brd.hash_key;
172 replace->score = score;
173 replace->mdf = move | (depth << 21) | (flag << 29);
175 if (SCORE_IS_MATE(score))
176 replace->score += score > 0 ? ply : -ply;
179 void
180 free_main_hashtable(void)
182 free(main_hash);
185 void
186 free_pawn_hashtable(void)
188 free(pawn_hash[WHITE]);
189 free(pawn_hash[BLACK]);
192 /* clear hashtables */
193 void
194 clear_main_hashtable(void)
196 hashtable_age = 0;
198 if (main_hash)
199 memset(main_hash, 0, 4 * (main_hash_mask + 1) * \
200 sizeof(struct main_hash_entry_t));
203 void
204 clear_pawn_hashtable(void)
206 if (pawn_hash[WHITE])
207 memset(pawn_hash[WHITE], 0, (pawn_hash_mask + 1) * \
208 sizeof(struct pawn_hash_entry_t));
209 if (pawn_hash[BLACK])
210 memset(pawn_hash[BLACK], 0, (pawn_hash_mask + 1) * \
211 sizeof(struct pawn_hash_entry_t));