Rev 33 | Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 33 | Rev 108 | ||
---|---|---|---|
Line 2... | Line 2... | ||
2 | #include "data.h" |
2 | #include "data.h" |
3 | #include "epdglue.h" |
3 | #include "epdglue.h" |
4 | /* last modified |
4 | /* last modified 05/12/15 */ |
5 | /* |
5 | /* |
6 | ******************************************************************************* |
6 | ******************************************************************************* |
7 | * * |
7 | * * |
8 | * Iterate() is the routine used to drive the iterated search. It * |
8 | * Iterate() is the routine used to drive the iterated search. It * |
9 | * repeatedly calls search, incrementing the search depth after each call, * |
9 | * repeatedly calls search, incrementing the search depth after each call, * |
Line 40... | Line 40... | ||
40 | * * |
40 | * * |
41 | ******************************************************************************* |
41 | ******************************************************************************* |
42 | */ |
42 | */ |
43 | int Iterate(int wtm, int search_type, int root_list_done) { |
43 | int Iterate(int wtm, int search_type, int root_list_done) { |
44 | TREE *const tree = block[0]; |
44 | TREE *const tree = block[0]; |
- | 45 | ROOT_MOVE temp_rm; |
|
45 | int i, |
46 | int i, alpha, beta, current_rm = 0, force_print = 0; |
46 | int value = 0, twtm, correct, correct_count; |
47 | int value = 0, twtm, correct, correct_count, npc, cpl, max; |
47 |
|
48 | unsigned int idle_time; |
- | 49 | char buff[32]; |
|
48 | #if (CPUS > 1) |
50 | #if (CPUS > 1) |
49 |
|
51 | # if defined(UNIX) // Pierre-Marie Baty -- missing conditional macro |
50 | pthread_t pt; |
52 | pthread_t pt; |
51 |
|
53 | # endif |
52 | #endif |
54 | #endif |
53 | 55 | ||
54 | /* |
56 | /* |
55 | ************************************************************ |
57 | ************************************************************ |
56 | * * |
58 | * * |
Line 58... | Line 60... | ||
58 | * we don't know whether we are searching for black or * |
60 | * we don't know whether we are searching for black or * |
59 | * white until we get to this point. * |
61 | * white until we get to this point. * |
60 | * * |
62 | * * |
61 | ************************************************************ |
63 | ************************************************************ |
62 | */ |
64 | */ |
63 | if (wtm) { |
- | |
64 |
|
65 | draw_score[black] = (wtm) ? -abs_draw_score : abs_draw_score; |
65 | draw_score[1] = abs_draw_score; |
- | |
66 | } else { |
- | |
67 | draw_score[0] = abs_draw_score; |
- | |
68 |
|
66 | draw_score[white] = (wtm) ? abs_draw_score : -abs_draw_score; |
69 | } |
- | |
70 | #if defined(NODES) |
67 | #if defined(NODES) |
71 | temp_search_nodes = search_nodes; |
68 | temp_search_nodes = search_nodes; |
72 | #endif |
69 | #endif |
73 | /* |
70 | /* |
74 | ************************************************************ |
71 | ************************************************************ |
75 | * * |
72 | * * |
76 | * Initialize statistical counters and such. * |
73 | * Initialize statistical counters and such. * |
77 | * * |
74 | * * |
78 | ************************************************************ |
75 | ************************************************************ |
79 | */ |
76 | */ |
80 | idle_time = 0; |
- | |
81 | tree->curmv[0] = 0; |
- | |
82 | abort_search = 0; |
77 | abort_search = 0; |
83 | book_move = 0; |
78 | book_move = 0; |
84 | program_start_time = ReadClock(); |
79 | program_start_time = ReadClock(); |
85 | start_time = ReadClock(); |
80 | start_time = ReadClock(); |
86 | root_wtm = wtm; |
81 | root_wtm = wtm; |
87 | kibitz_depth = 0; |
82 | kibitz_depth = 0; |
88 | tree->nodes_searched = 0; |
83 | tree->nodes_searched = 0; |
89 | tree->fail_highs = 0; |
84 | tree->fail_highs = 0; |
90 | tree->fail_high_first_move = 0; |
85 | tree->fail_high_first_move = 0; |
91 | parallel_splits = 0; |
86 | parallel_splits = 0; |
- | 87 | parallel_splits_wasted = 0; |
|
92 | parallel_aborts = 0; |
88 | parallel_aborts = 0; |
- | 89 | parallel_joins = 0; |
|
- | 90 | for (i = 0; i < (int) smp_max_threads; i++) { // Pierre-Marie Baty -- added type cast |
|
- | 91 | thread[i].max_blocks = 0; |
|
- | 92 | thread[i].tree = 0; |
|
- | 93 | thread[i].idle = 0; |
|
- | 94 | thread[i].terminate = 0; |
|
- | 95 | } |
|
- | 96 | thread[0].tree = block[0]; |
|
93 | correct_count = 0; |
97 | correct_count = 0; |
94 | burp = 15 * 100; |
98 | burp = 15 * 100; |
95 | transposition_age = (transposition_age + 1) & 0x1ff; |
99 | transposition_age = (transposition_age + 1) & 0x1ff; |
96 | next_time_check = nodes_between_time_checks; |
100 | next_time_check = nodes_between_time_checks; |
97 | tree->evaluations = 0; |
101 | tree->evaluations = 0; |
98 | tree->egtb_probes = 0; |
102 | tree->egtb_probes = 0; |
99 | tree-> |
103 | tree->egtb_hits = 0; |
100 | tree->extensions_done = 0; |
104 | tree->extensions_done = 0; |
101 | tree->qchecks_done = 0; |
105 | tree->qchecks_done = 0; |
102 | tree->reductions_done = 0; |
- | |
103 | tree->moves_fpruned = 0; |
106 | tree->moves_fpruned = 0; |
- | 107 | tree->moves_mpruned = 0; |
|
- | 108 | for (i = 0; i < 16; i++) { |
|
- | 109 | tree->LMR_done[i] = 0; |
|
- | 110 | tree->null_done[i] = 0; |
|
- | 111 | } |
|
104 | root_wtm = wtm; |
112 | root_wtm = wtm; |
105 | /* |
113 | /* |
106 | ************************************************************ |
114 | ************************************************************ |
107 | * * |
115 | * * |
108 | * We do a quick check to see if this position has a known * |
116 | * We do a quick check to see if this position has a known * |
Line 118... | Line 126... | ||
118 | * (based on a normal search / evaluation but with a lower * |
126 | * (based on a normal search / evaluation but with a lower * |
119 | * time limit) from the book moves given. * |
127 | * time limit) from the book moves given. * |
120 | * * |
128 | * * |
121 | ************************************************************ |
129 | ************************************************************ |
122 | */ |
130 | */ |
- | 131 | if (!root_list_done) |
|
- | 132 | RootMoveList(wtm); |
|
123 | if (booking || !Book(tree, wtm |
133 | if (booking || !Book(tree, wtm)) |
124 | do { |
134 | do { |
125 | if (abort_search) |
135 | if (abort_search) |
126 | break; |
136 | break; |
127 | #if !defined(NOEGTB) |
137 | #if !defined(NOEGTB) |
128 | if (EGTB_draw && !puzzling && swindle_mode) |
138 | if (EGTB_draw && !puzzling && swindle_mode) |
129 | EGTB_use = 0; |
139 | EGTB_use = 0; |
130 | else |
140 | else |
131 | EGTB_use = EGTBlimit; |
141 | EGTB_use = EGTBlimit; |
132 | if (EGTBlimit && !EGTB_use) |
142 | if (EGTBlimit && !EGTB_use) |
133 | Print( |
143 | Print(32, "Drawn at root, trying for swindle.\n"); |
134 | #endif |
144 | #endif |
135 | /* |
145 | /* |
136 | ************************************************************ |
146 | ************************************************************ |
137 | * * |
147 | * * |
138 | * The first action for a real search is to generate the * |
148 | * The first action for a real search is to generate the * |
Line 149... | Line 159... | ||
149 | * book random 0) which would have already inserted just * |
159 | * book random 0) which would have already inserted just * |
150 | * the moves that should be searched. * |
160 | * the moves that should be searched. * |
151 | * * |
161 | * * |
152 | ************************************************************ |
162 | ************************************************************ |
153 | */ |
163 | */ |
154 | if (!root_list_done) |
- | |
155 | RootMoveList(wtm); |
- | |
156 | if (n_root_moves == 0) { |
164 | if (n_root_moves == 0) { |
157 | program_end_time = ReadClock(); |
165 | program_end_time = ReadClock(); |
158 | tree->pv[0].pathl = 0; |
166 | tree->pv[0].pathl = 0; |
159 | tree->pv[0].pathd = 0; |
167 | tree->pv[0].pathd = 0; |
160 | if (Check(wtm)) |
168 | if (Check(wtm)) |
161 | value = -(MATE - 1); |
169 | value = -(MATE - 1); |
162 | else |
170 | else |
163 | value = DrawScore(wtm); |
171 | value = DrawScore(wtm); |
164 | Print( |
172 | Print(2, " depth time score variation\n"); |
165 | Print( |
173 | Print(2, " (no moves)\n"); |
166 | tree->nodes_searched = 1; |
174 | tree->nodes_searched = 1; |
167 | if (!puzzling) |
175 | if (!puzzling) |
168 | last_root_value = value; |
176 | last_root_value = value; |
169 | return value; |
177 | return value; |
170 | } |
178 | } |
Line 178... | Line 186... | ||
178 | * by search. * |
186 | * by search. * |
179 | * * |
187 | * * |
180 | ************************************************************ |
188 | ************************************************************ |
181 | */ |
189 | */ |
182 | TimeSet(search_type); |
190 | TimeSet(search_type); |
183 |
|
191 | iteration = 1; |
184 | noise_block = 0; |
192 | noise_block = 0; |
- | 193 | force_print = 0; |
|
185 | if (last_pv.pathd > 1) { |
194 | if (last_pv.pathd > 1) { |
186 |
|
195 | iteration = last_pv.pathd + 1; |
187 | value = last_root_value; |
196 | value = last_root_value; |
188 | tree->pv[0] = last_pv; |
197 | tree->pv[0] = last_pv; |
- | 198 | root_moves[0].path = tree->pv[0]; |
|
189 | noise_block = 1; |
199 | noise_block = 1; |
- | 200 | force_print = 1; |
|
190 | } else |
201 | } else |
191 | difficulty = 100; |
202 | difficulty = 100; |
192 | Print( |
203 | Print(2, " depth time score variation (%d)\n", |
193 |
|
204 | iteration); |
194 | abort_search = 0; |
205 | abort_search = 0; |
195 | /* |
206 | /* |
196 | ************************************************************ |
207 | ************************************************************ |
197 | * * |
208 | * * |
198 | * Set the initial search bounds based on the last search * |
209 | * Set the initial search bounds based on the last search * |
199 | * or default values. * |
210 | * or default values. * |
200 | * * |
211 | * * |
201 | ************************************************************ |
212 | ************************************************************ |
202 | */ |
213 | */ |
203 | tree->pv[0] = last_pv; |
214 | tree->pv[0] = last_pv; |
204 | if ( |
215 | if (iteration > 1) { |
205 |
|
216 | alpha = Max(-MATE, last_value - 16); |
206 |
|
217 | beta = Min(MATE, last_value + 16); |
207 | } else { |
218 | } else { |
208 |
|
219 | alpha = -MATE; |
209 |
|
220 | beta = MATE; |
210 | } |
221 | } |
211 | /* |
222 | /* |
212 | ************************************************************ |
223 | ************************************************************ |
213 | * * |
224 | * * |
214 | * If we are using multiple threads, and they have not * |
225 | * If we are using multiple threads, and they have not * |
215 | * been started yet, then start them now as the search is * |
226 | * been started yet, then start them now as the search is * |
216 | * ready to begin. * |
227 | * ready to begin. * |
- | 228 | * * |
|
- | 229 | * If we are using CPU affinity, we need to set this up * |
|
- | 230 | * for thread 0 since it could have changed since we * |
|
- | 231 | * initialized everything. * |
|
217 | * * |
232 | * * |
218 | ************************************************************ |
233 | ************************************************************ |
219 | */ |
234 | */ |
220 | #if (CPUS > 1) |
235 | #if (CPUS > 1) |
221 | if (smp_max_threads > |
236 | if ((int) smp_max_threads > smp_threads + 1) { // Pierre-Marie Baty -- added type cast |
222 | long proc; |
237 | long proc; |
223 | 238 | ||
224 | initialized_threads = 1; |
239 | initialized_threads = 1; |
225 | Print( |
240 | Print(32, "starting thread"); |
226 | for (proc = smp_threads + 1; proc < smp_max_threads; proc++) { |
241 | for (proc = smp_threads + 1; proc < (int) smp_max_threads; proc++) { // Pierre-Marie Baty -- added type cast |
227 | Print( |
242 | Print(32, " %d", proc); |
228 | thread[proc].tree = 0; |
- | |
229 | # if defined(UNIX) |
243 | # if defined(UNIX) |
230 | pthread_create(&pt, &attributes, ThreadInit, (void *) proc); |
244 | pthread_create(&pt, &attributes, ThreadInit, (void *) proc); |
231 | # else |
245 | # else |
232 | NumaStartThread(ThreadInit, (void *) proc); |
246 | NumaStartThread(ThreadInit, (void *) proc); |
233 | # endif |
247 | # endif |
234 | smp_threads++; |
248 | smp_threads++; |
235 | } |
249 | } |
236 | Print( |
250 | Print(32, " <done>\n"); |
237 | } |
251 | } |
238 | WaitForAllThreadsInitialized(); |
252 | WaitForAllThreadsInitialized(); |
- | 253 | ThreadAffinity(smp_affinity); |
|
239 | #endif |
254 | #endif |
240 | if (search_nodes) |
255 | if (search_nodes) |
241 | nodes_between_time_checks = search_nodes; |
256 | nodes_between_time_checks = (unsigned int) search_nodes; // Pierre-Marie Baty -- added type cast |
242 | for (; iteration_depth <= MAXPLY - 5; iteration_depth++) { |
- | |
243 | /* |
257 | /* |
244 | ************************************************************ |
258 | ************************************************************ |
245 | * * |
259 | * * |
- | 260 | * Main iterative-deepening loop starts here. We either * |
|
- | 261 | * start at depth = 1, or if we are pondering and have a * |
|
- | 262 | * PV from the previous search, we use that to set the * |
|
- | 263 | * starting depth. * |
|
- | 264 | * * |
|
246 | * |
265 | * First install the old PV into the hash table so that * |
247 | * these moves will be |
266 | * these moves will be searched first. We do this since * |
248 | * the last iteration done could have overwritten the PV * |
267 | * the last iteration done could have overwritten the PV * |
249 | * as the last few root moves were searched. * |
268 | * as the last few root moves were searched. * |
250 | * * |
269 | * * |
251 | ************************************************************ |
270 | ************************************************************ |
252 | */ |
271 | */ |
- | 272 | for (; iteration <= MAXPLY - 5; iteration++) { |
|
253 | twtm = wtm; |
273 | twtm = wtm; |
254 | for (i = 1; i < (int) tree->pv[0].pathl; i++) { |
274 | for (i = 1; i < (int) tree->pv[0].pathl; i++) { |
255 | if (!VerifyMove(tree, i, twtm, tree->pv[0].path[i])) { |
275 | if (!VerifyMove(tree, i, twtm, tree->pv[0].path[i])) { |
256 | Print( |
276 | Print(2048, "ERROR, not installing bogus pv info at ply=%d\n", i); |
257 | Print( |
277 | Print(2048, "not installing from=%d to=%d piece=%d\n", |
258 | From(tree->pv[0].path[i]), To(tree->pv[0].path[i]), |
278 | From(tree->pv[0].path[i]), To(tree->pv[0].path[i]), |
259 | Piece(tree->pv[0].path[i])); |
279 | Piece(tree->pv[0].path[i])); |
260 | Print( |
280 | Print(2048, "pathlen=%d\n", tree->pv[0].pathl); |
261 | break; |
281 | break; |
262 | } |
282 | } |
263 | HashStorePV(tree, twtm, i); |
283 | HashStorePV(tree, twtm, i); |
264 | MakeMove(tree, i, tree->pv[0].path[i] |
284 | MakeMove(tree, i, twtm, tree->pv[0].path[i]); |
265 | twtm = Flip(twtm); |
285 | twtm = Flip(twtm); |
266 | } |
286 | } |
267 | for (i--; i > 0; i--) { |
287 | for (i--; i > 0; i--) { |
268 | twtm = Flip(twtm); |
288 | twtm = Flip(twtm); |
269 | UnmakeMove(tree, i, tree->pv[0].path[i] |
289 | UnmakeMove(tree, i, twtm, tree->pv[0].path[i]); |
270 | } |
290 | } |
271 | /* |
291 | /* |
272 | ************************************************************ |
292 | ************************************************************ |
273 | * * |
293 | * * |
274 | * Now we call Search() and start the next search * |
294 | * Now we call Search() and start the next search * |
Line 285... | Line 305... | ||
285 | * of the clock unnecessarily. * |
305 | * of the clock unnecessarily. * |
286 | * * |
306 | * * |
287 | ************************************************************ |
307 | ************************************************************ |
288 | */ |
308 | */ |
289 | if (trace_level) { |
309 | if (trace_level) { |
290 |
|
310 | Print(32, "==================================\n"); |
291 |
|
311 | Print(32, "= search iteration %2d =\n", iteration); |
292 |
|
312 | Print(32, "==================================\n"); |
293 | } |
313 | } |
294 | if (tree->nodes_searched) { |
314 | if (tree->nodes_searched) { |
295 | nodes_between_time_checks = |
315 | nodes_between_time_checks = |
- | 316 | nodes_per_second / (10 * Max(smp_max_threads, 1)); |
|
296 | if (!analyze_mode) { |
317 | if (!analyze_mode) { |
297 | if (time_limit |
318 | if (time_limit < 1000) |
- | 319 | nodes_between_time_checks /= 10; |
|
298 |
|
320 | if (time_limit < 100) |
299 | nodes_between_time_checks /= 10; |
321 | nodes_between_time_checks /= 10; |
300 | else |
- | |
301 | nodes_between_time_checks /= 100; |
- | |
302 | } else |
322 | } else |
303 | nodes_between_time_checks = Min(nodes_per_second, 1000000); |
323 | nodes_between_time_checks = Min(nodes_per_second, 1000000); |
304 | #if defined(SKILL) |
- | |
305 | if (skill > 50) |
- | |
306 | nodes_between_time_checks = Max(nodes_between_time_checks, 10000); |
- | |
307 | #endif |
- | |
308 | } |
324 | } |
309 | if (search_nodes) |
325 | if (search_nodes) |
310 | nodes_between_time_checks = |
326 | nodes_between_time_checks = (unsigned int) (search_nodes - tree->nodes_searched); // Pierre-Marie Baty -- added type cast |
311 | nodes_between_time_checks = |
327 | nodes_between_time_checks = |
312 | Min(nodes_between_time_checks, MAX_TC_NODES); |
328 | Min(nodes_between_time_checks, MAX_TC_NODES); |
313 | next_time_check = nodes_between_time_checks; |
329 | next_time_check = nodes_between_time_checks; |
314 | /* |
330 | /* |
315 | ************************************************************ |
331 | ************************************************************ |
Line 323... | Line 339... | ||
323 | * * |
339 | * * |
324 | ************************************************************ |
340 | ************************************************************ |
325 | */ |
341 | */ |
326 | failhi_delta = 16; |
342 | failhi_delta = 16; |
327 | faillo_delta = 16; |
343 | faillo_delta = 16; |
- | 344 | for (i = 0; i < n_root_moves; i++) { |
|
- | 345 | if (i || iteration == 1) |
|
- | 346 | root_moves[i].path.pathv = -99999999; |
|
- | 347 | root_moves[i].status &= 4; |
|
- | 348 | } |
|
328 | while (1) { |
349 | while (1) { |
329 | thread[0].tree = block[0]; |
- | |
330 | tree->inchk[1] = Check(wtm); |
- | |
331 | if (smp_max_threads > 1) |
350 | if (smp_max_threads > 1) |
332 | smp_split = 1; |
351 | smp_split = 1; |
333 |
|
352 | rep_index--; |
334 | value = |
- | |
335 |
|
353 | value = Search(tree, 1, iteration, wtm, alpha, beta, Check(wtm), 0); |
336 |
|
354 | rep_index++; |
337 | end_time = ReadClock(); |
355 | end_time = ReadClock(); |
338 | if (abort_search) |
356 | if (abort_search) |
339 | break; |
357 | break; |
- | 358 | for (current_rm = 0; current_rm < n_root_moves; current_rm++) |
|
340 |
|
359 | if (tree->pv[0].path[1] == root_moves[current_rm].move) |
341 |
|
360 | break; |
342 | /* |
361 | /* |
343 | ************************************************************ |
362 | ************************************************************ |
344 | * * |
363 | * * |
345 | * Check for the case where we get a score back that is * |
364 | * Check for the case where we get a score back that is * |
346 | * greater than or equal to beta. This is called a fail * |
365 | * greater than or equal to beta. This is called a fail * |
Line 365... | Line 384... | ||
365 | * mind at the root. (If we are failing high on the first * |
384 | * mind at the root. (If we are failing high on the first * |
366 | * root move we skip this update.) * |
385 | * root move we skip this update.) * |
367 | * * |
386 | * * |
368 | ************************************************************ |
387 | ************************************************************ |
369 | */ |
388 | */ |
370 | if (value >= |
389 | if (value >= beta) { |
371 |
|
390 | beta = Min(beta + failhi_delta, MATE); |
372 | failhi_delta *= 2; |
391 | failhi_delta *= 2; |
373 | if (failhi_delta > 10 * PAWN_VALUE) |
392 | if (failhi_delta > 10 * PAWN_VALUE) |
374 | failhi_delta = 99999; |
393 | failhi_delta = 99999; |
375 | root_moves[ |
394 | root_moves[current_rm].status &= 7; |
- | 395 | root_moves[current_rm].bm_age = 4; |
|
376 | if ((root_moves[ |
396 | if ((root_moves[current_rm].status & 2) == 0) |
377 | difficulty = ComputeDifficulty(difficulty, +1); |
397 | difficulty = ComputeDifficulty(difficulty, +1); |
378 | root_moves[ |
398 | root_moves[current_rm].status |= 2; |
379 | if (tree->nodes_searched > noise_level) { |
- | |
380 | fh_indicator = (wtm) ? "++" : "--"; |
- | |
381 |
|
399 | DisplayFail(tree, 1, 5, wtm, end_time - start_time, |
382 |
|
400 | root_moves[current_rm].move, value, force_print); |
383 | if (display_options & 64) |
- | |
384 |
|
401 | temp_rm = root_moves[current_rm]; |
385 | if ((display_options & 64) && !wtm) |
- | |
386 | Print(2, "... "); |
- | |
387 | Print(2, "%s! ", OutputMove(tree, tree->pv[1].path[1], 1, wtm)); |
- | |
388 | Print(2, "(%c%s) \n", (wtm) ? '>' : '<', |
- | |
389 | DisplayEvaluationKibitz(old_root_beta, wtm)); |
- | |
390 |
|
402 | for (i = current_rm; i > 0; i--) |
391 |
|
403 | root_moves[i] = root_moves[i - 1]; |
392 | sprintf_s(kibitz_text, sizeof (kibitz_text), " %d.", move_number); // Pierre-Marie Baty -- use safe version |
- | |
393 | if ((display_options & 64) && !wtm) |
- | |
394 | strcat_s(kibitz_text, sizeof (kibitz_text), " ..."); // Pierre-Marie Baty -- use safe version |
- | |
395 | sprintf(kibitz_text + strlen(kibitz_text), " %s!", |
- | |
396 | OutputMove(tree, tree->pv[1].path[1], 1, wtm)); |
- | |
397 | idle_percent = |
- | |
398 |
|
404 | root_moves[0] = temp_rm; |
399 | 100 * idle_time / (smp_max_threads * (end_time - |
- | |
400 | start_time) + 1)); |
- | |
401 | Kibitz(6, wtm, iteration_depth, end_time - start_time, value, |
- | |
402 | tree->nodes_searched, idle_percent, |
- | |
403 | tree->egtb_probes_successful, kibitz_text); |
- | |
404 |
|
405 | } |
405 | /* |
406 | /* |
406 | ************************************************************ |
407 | ************************************************************ |
407 | * * |
408 | * * |
408 | * Check for the case where we get a score back that is * |
409 | * Check for the case where we get a score back that is * |
409 | * less than or equal to alpha. This is called a fail * |
410 | * less than or equal to alpha. This is called a fail * |
Line 428... | Line 429... | ||
428 | * the first move at the root, and we don't want to stop * |
429 | * the first move at the root, and we don't want to stop * |
429 | * before we have a chance to find a better one. * |
430 | * before we have a chance to find a better one. * |
430 | * * |
431 | * * |
431 | ************************************************************ |
432 | ************************************************************ |
432 | */ |
433 | */ |
433 |
|
434 | else if (value <= alpha) { |
434 |
|
435 | alpha = Max(alpha - faillo_delta, -MATE); |
435 | faillo_delta *= 2; |
436 | faillo_delta *= 2; |
436 | if (faillo_delta > 10 * PAWN_VALUE) |
437 | if (faillo_delta > 10 * PAWN_VALUE) |
437 | faillo_delta = 99999; |
438 | faillo_delta = 99999; |
438 | root_moves[ |
439 | root_moves[current_rm].status &= 7; |
439 | if ((root_moves[ |
440 | if ((root_moves[current_rm].status & 1) == 0) |
440 | difficulty = ComputeDifficulty(Max(100, difficulty), -1); |
441 | difficulty = ComputeDifficulty(Max(100, difficulty), -1); |
441 | root_moves[ |
442 | root_moves[current_rm].status |= 1; |
442 | if (tree->nodes_searched > noise_level && !abort_search) { |
- | |
443 | fl_indicator = (wtm) ? "--" : "++"; |
- | |
444 | Print(4, " %2i %s %2s ", iteration_depth, |
- | |
445 |
|
443 | DisplayFail(tree, 2, 5, wtm, end_time - start_time, |
446 | if (display_options & 64) |
- | |
447 |
|
444 | root_moves[current_rm].move, value, force_print); |
448 | if ((display_options & 64) && !wtm) |
- | |
449 | Print(4, "... "); |
- | |
450 | Print(4, "%s? ", OutputMove(tree, root_moves[0].move, 1, wtm)); |
- | |
451 | Print(4, "(%c%s) \n", (Flip(wtm)) ? '>' : '<', |
- | |
452 | DisplayEvaluationKibitz(old_root_alpha, wtm)); |
- | |
453 | } |
- | |
454 | } else |
445 | } else |
455 | break; |
446 | break; |
456 | } |
447 | } |
457 | if (value > |
448 | if (value > alpha && value < beta) |
458 | last_root_value = value; |
449 | last_root_value = value; |
459 | /* |
450 | /* |
460 | ************************************************************ |
451 | ************************************************************ |
461 | * * |
452 | * * |
462 | * If we are running a test suite, check to see if we can * |
453 | * If we are running a test suite, check to see if we can * |
Line 469... | Line 460... | ||
469 | correct = solution_type; |
460 | correct = solution_type; |
470 | for (i = 0; i < number_of_solutions; i++) { |
461 | for (i = 0; i < number_of_solutions; i++) { |
471 | if (!solution_type) { |
462 | if (!solution_type) { |
472 | if (solutions[i] == tree->pv[0].path[1]) |
463 | if (solutions[i] == tree->pv[0].path[1]) |
473 | correct = 1; |
464 | correct = 1; |
474 | } else if (solutions[i] == |
465 | } else if (solutions[i] == root_moves[current_rm].move) |
475 | correct = 0; |
466 | correct = 0; |
476 | } |
467 | } |
477 | if (correct) |
468 | if (correct) |
478 | correct_count++; |
469 | correct_count++; |
479 | else |
470 | else |
Line 486... | Line 477... | ||
486 | * those since they are potential best moves again. * |
477 | * those since they are potential best moves again. * |
487 | * * |
478 | * * |
488 | ************************************************************ |
479 | ************************************************************ |
489 | */ |
480 | */ |
490 | for (i = 0; i < n_root_moves; i++) { |
481 | for (i = 0; i < n_root_moves; i++) { |
- | 482 | root_moves[i].status &= 3; |
|
491 | if (root_moves[i].bm_age) |
483 | if (root_moves[i].bm_age) |
492 | root_moves[i].bm_age--; |
484 | root_moves[i].bm_age--; |
493 | if (root_moves[i].bm_age) |
485 | if (root_moves[i].bm_age) |
494 | root_moves[i].status &= 0xfb; |
- | |
495 | else |
- | |
496 | root_moves[i].status |= 4; |
486 | root_moves[i].status |= 4; |
497 | } |
487 | } |
- | 488 | SortRootMoves(); |
|
498 | difficulty = ComputeDifficulty(difficulty, 0); |
489 | difficulty = ComputeDifficulty(difficulty, 0); |
499 | /* |
490 | /* |
500 | ************************************************************ |
491 | ************************************************************ |
501 | * * |
492 | * * |
502 | * If requested, print the ply=1 move list along with the * |
493 | * If requested, print the ply=1 move list along with the * |
503 | * flags for each move. Once we print this (if requested) * |
494 | * flags for each move. Once we print this (if requested) * |
504 | * we can then clear all of the status flags (except the * |
495 | * we can then clear all of the status flags (except the * |
505 | * " |
496 | * "do not search in parallel or reduce" flag) to prepare * |
506 | * for the start of the next iteration, since that is the * |
497 | * for the start of the next iteration, since that is the * |
507 | * only flag that needs to be carried forward to the next * |
498 | * only flag that needs to be carried forward to the next * |
508 | * iteration. * |
499 | * iteration. * |
509 | * * |
500 | * * |
510 | ************************************************************ |
501 | ************************************************************ |
511 | */ |
502 | */ |
512 | if (display_options & |
503 | if (display_options & 64) { |
513 | Print( |
504 | Print(64, " rmove score age S ! ?\n"); |
514 | for (i = 0; i < n_root_moves; i++) { |
505 | for (i = 0; i < n_root_moves; i++) { |
515 | Print( |
506 | Print(64, " %10s ", OutputMove(tree, 1, wtm, root_moves[i].move)); |
- | 507 | if (root_moves[i].path.pathv > -MATE) |
|
- | 508 | Print(64, "%s", DisplayEvaluation(root_moves[i].path.pathv, |
|
- | 509 | wtm)); |
|
- | 510 | else |
|
- | 511 | Print(64, " -----"); |
|
516 |
|
512 | Print(64, " %d %d %d %d\n", root_moves[i].bm_age, |
517 | (root_moves[i].status & 4) != 0, |
513 | (root_moves[i].status & 4) != 0, |
518 | (root_moves[i].status & 2) != 0, |
514 | (root_moves[i].status & 2) != 0, |
519 | (root_moves[i].status & 1) != 0); |
515 | (root_moves[i].status & 1) != 0); |
520 | } |
516 | } |
521 | } |
517 | } |
522 | for (i = 0; i < n_root_moves; i++) |
- | |
523 | root_moves[i].status &= 4; |
- | |
524 | /* |
518 | /* |
525 | ************************************************************ |
519 | ************************************************************ |
526 | * * |
520 | * * |
527 | * Here we simply display the PV from the current search * |
521 | * Here we simply display the PV from the current search * |
528 | * iteration, and then set the aspiration for the next * |
522 | * iteration, and then set the aspiration for the next * |
529 | * iteration to the current score +/- 16. * |
523 | * iteration to the current score +/- 16. * |
530 | * * |
524 | * * |
531 | ************************************************************ |
525 | ************************************************************ |
532 | */ |
526 | */ |
533 | if (end_time - start_time > 10) |
527 | if (end_time - start_time > 10) |
534 | nodes_per_second = |
528 | nodes_per_second = (unsigned int) // Pierre-Marie Baty -- added type cast |
535 |
|
529 | (tree->nodes_searched * 100 / (uint64_t) (end_time - start_time)); |
536 | else |
530 | else |
537 | nodes_per_second = 1000000; |
531 | nodes_per_second = 1000000; |
- | 532 | tree->pv[0] = root_moves[0].path; |
|
538 | if (!abort_search && value != -(MATE - 1)) { |
533 | if (!abort_search && value != -(MATE - 1)) { |
539 | if ( |
534 | if (end_time - start_time >= noise_level) { |
540 | DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0] |
535 | DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0], |
- | 536 | force_print); |
|
541 | noise_block = 0; |
537 | noise_block = 0; |
542 | } |
538 | } else |
- | 539 | noise_block = 1; |
|
543 | } |
540 | } |
544 |
|
541 | alpha = Max(-MATE, value - 16); |
545 |
|
542 | beta = Min(MATE, value + 16); |
546 | /* |
543 | /* |
547 | ************************************************************ |
544 | ************************************************************ |
548 | * * |
545 | * * |
549 | * There are multiple termination criteria that are used. * |
546 | * There are multiple termination criteria that are used. * |
550 | * The first and most obvious is that we have exceeded the * |
547 | * The first and most obvious is that we have exceeded the * |
Line 559... | Line 556... | ||
559 | * * |
556 | * * |
560 | ************************************************************ |
557 | ************************************************************ |
561 | */ |
558 | */ |
562 | if (TimeCheck(tree, 0)) |
559 | if (TimeCheck(tree, 0)) |
563 | break; |
560 | break; |
564 | if ( |
561 | if (iteration > 3 && value > 32000 && value >= (MATE - iteration + 3) |
565 | value >= (MATE - iteration_depth + 3) |
- | |
566 | && value > last_mate_score) |
562 | && value > last_mate_score) |
567 | break; |
563 | break; |
568 | if (( |
564 | if ((iteration >= search_depth) && search_depth) |
569 | break; |
565 | break; |
570 | if (abort_search) |
566 | if (abort_search) |
571 | break; |
567 | break; |
572 | end_time = ReadClock() - start_time; |
568 | end_time = ReadClock() - start_time; |
573 | if (correct_count >= early_exit) |
569 | if (correct_count >= early_exit) |
574 | break; |
570 | break; |
575 | #if !defined(NOEGTB) |
571 | #if !defined(NOEGTB) |
576 | if ( |
572 | if (iteration > EGTB_depth + 10 && TotalAllPieces <= EGTBlimit && |
577 |
|
573 | EGTB_use && EGTBProbe(tree, 1, wtm, &i)) |
578 | break; |
574 | break; |
579 | #endif |
575 | #endif |
580 | if (search_nodes && tree->nodes_searched >= search_nodes) |
576 | if (search_nodes && tree->nodes_searched >= search_nodes) |
581 | break; |
577 | break; |
582 | } |
578 | } |
Line 602... | Line 598... | ||
602 | * * |
598 | * * |
603 | ************************************************************ |
599 | ************************************************************ |
604 | */ |
600 | */ |
605 | end_time = ReadClock(); |
601 | end_time = ReadClock(); |
606 | if (end_time > 10) |
602 | if (end_time > 10) |
607 | nodes_per_second = |
603 | nodes_per_second = (unsigned int) // Pierre-Marie Baty -- added type cast |
608 | ( |
604 | ((uint64_t) tree->nodes_searched * 100 / Max((uint64_t) end_time - |
609 | start_time |
605 | start_time, 1)); |
610 | if (abort_search != 2 && !puzzling) { |
606 | if (abort_search != 2 && !puzzling) { |
611 | if (noise_block) |
607 | if (noise_block) |
612 | DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0]); |
608 | DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0], 1); |
613 | tree->evaluations = (tree->evaluations) ? tree->evaluations : 1; |
609 | tree->evaluations = (tree->evaluations) ? tree->evaluations : 1; |
614 | tree->fail_highs++; |
610 | tree->fail_highs++; |
615 | tree->fail_high_first_move++; |
611 | tree->fail_high_first_move++; |
- | 612 | idle_time = 0; |
|
- | 613 | for (i = 0; i < (int) smp_max_threads; i++) // Pierre-Marie Baty -- added type cast |
|
- | 614 | idle_time += thread[i].idle; |
|
616 |
|
615 | busy_percent = |
617 | 100 - Min(100, |
616 | 100 - Min(100, |
618 | 100 * idle_time / (smp_max_threads * (end_time - start_time) + |
617 | 100 * idle_time / (smp_max_threads * (end_time - start_time) + |
619 | 1)); |
618 | 1)); |
620 | Print(8, " time=%s(%d%%)", |
619 | Print(8, " time=%s(%d%%)", |
621 | DisplayTimeKibitz(end_time - start_time), |
620 | DisplayTimeKibitz(end_time - start_time), busy_percent); |
622 | Print(8, " |
621 | Print(8, " nodes=%" PRIu64 "(%s)", tree->nodes_searched, |
- | 622 | DisplayKMB(tree->nodes_searched, 0)); |
|
623 | Print(8, " fh1=%d%%", |
623 | Print(8, " fh1=%d%%", |
624 | tree->fail_high_first_move * 100 / tree->fail_highs); |
624 | tree->fail_high_first_move * 100 / tree->fail_highs); |
- | 625 | Print(8, " pred=%d", predicted); |
|
- | 626 | Print(8, " nps=%s\n", DisplayKMB(nodes_per_second, 0)); |
|
- | 627 | Print(8, " chk=%s", DisplayKMB(tree->extensions_done, 0)); |
|
- | 628 | Print(8, " qchk=%s", DisplayKMB(tree->qchecks_done, 0)); |
|
- | 629 | Print(8, " fp=%s", DisplayKMB(tree->moves_fpruned, 0)); |
|
- | 630 | Print(8, " mcp=%s", DisplayKMB(tree->moves_mpruned, 0)); |
|
625 | Print(8, " 50move=%d", Reversible(0)); |
631 | Print(8, " 50move=%d", Reversible(0)); |
- | 632 | if (tree->egtb_hits) |
|
626 | Print(8, " |
633 | Print(8, " egtb=%s", DisplayKMB(tree->egtb_hits, 0)); |
- | 634 | Print(8, "\n"); |
|
627 | Print( |
635 | Print(8, " LMReductions:"); |
- | 636 | npc = 21; |
|
- | 637 | cpl = 75; |
|
- | 638 | for (i = 1; i < 16; i++) |
|
- | 639 | if (tree->LMR_done[i]) { |
|
628 |
|
640 | sprintf(buff, "%d/%s", i, DisplayKMB(tree->LMR_done[i], 0)); |
- | 641 | if (npc + (int)strlen(buff) > cpl) { // Pierre-Marie Baty -- added type cast |
|
- | 642 | Print(8, "\n "); |
|
- | 643 | npc = 12; |
|
- | 644 | } |
|
- | 645 | Print(8, " %s", buff); |
|
- | 646 | npc += strlen(buff) + 2; |
|
- | 647 | } |
|
- | 648 | if (npc) |
|
- | 649 | Print(8, "\n"); |
|
- | 650 | npc = 24; |
|
- | 651 | cpl = 75; |
|
- | 652 | if (tree->null_done[null_depth]) |
|
629 | Print( |
653 | Print(8, " null-move (R):"); |
- | 654 | for (i = null_depth; i < 16; i++) |
|
- | 655 | if (tree->null_done[i]) { |
|
630 |
|
656 | sprintf(buff, "%d/%s", i, DisplayKMB(tree->null_done[i], 0)); |
- | 657 | if (npc + (int)strlen(buff) > cpl) { // Pierre-Marie Baty -- added type cast |
|
- | 658 | Print(8, "\n "); |
|
- | 659 | npc = 12; |
|
- | 660 | } |
|
631 | Print( |
661 | Print(8, " %s", buff); |
- | 662 | npc += strlen(buff) + 2; |
|
- | 663 | } |
|
- | 664 | if (npc) |
|
- | 665 | Print(8, "\n"); |
|
- | 666 | if (parallel_splits) { |
|
- | 667 | max = 0; |
|
- | 668 | for (i = 0; i < (int) smp_max_threads; i++) { // Pierre-Marie Baty -- added type cast |
|
- | 669 | max = Max(max, PopCnt(thread[i].max_blocks)); |
|
- | 670 | game_max_blocks |= thread[i].max_blocks; |
|
- | 671 | } |
|
632 | Print( |
672 | Print(8, " splits=%s", DisplayKMB(parallel_splits, 0)); |
633 | Print( |
673 | Print(8, "(%s)", DisplayKMB(parallel_splits_wasted, 0)); |
634 |
|
674 | Print(8, " aborts=%s", DisplayKMB(parallel_aborts, 0)); |
635 | Print( |
675 | Print(8, " joins=%s", DisplayKMB(parallel_joins, 0)); |
636 | Print( |
676 | Print(8, " data=%d%%(%d%%)\n", 100 * max / 64, |
- | 677 | 100 * PopCnt(game_max_blocks) / 64); |
|
- | 678 | } |
|
637 | } |
679 | } |
638 | } while (0); |
680 | } while (0); |
639 | /* |
681 | /* |
640 | ************************************************************ |
682 | ************************************************************ |
641 | * * |
683 | * * |
Line 647... | Line 689... | ||
647 | */ |
689 | */ |
648 | else { |
690 | else { |
649 | last_root_value = 0; |
691 | last_root_value = 0; |
650 | value = 0; |
692 | value = 0; |
651 | book_move = 1; |
693 | book_move = 1; |
652 | tree->pv[0] = tree->pv[1]; |
- | |
653 | if (analyze_mode) |
694 | if (analyze_mode) |
654 | Kibitz(4, wtm, 0, 0, 0, 0, 0, 0, kibitz_text); |
695 | Kibitz(4, wtm, 0, 0, 0, 0, 0, 0, kibitz_text); |
655 | } |
696 | } |
656 | /* |
697 | /* |
657 | ************************************************************ |
698 | ************************************************************ |
Line 666... | Line 707... | ||
666 | * * |
707 | * * |
667 | ************************************************************ |
708 | ************************************************************ |
668 | */ |
709 | */ |
669 | if (smp_nice && ponder == 0 && smp_threads) { |
710 | if (smp_nice && ponder == 0 && smp_threads) { |
670 | int proc; |
711 | int proc; |
- | 712 | ||
671 | Print( |
713 | Print(64, "terminating SMP processes.\n"); |
672 | for (proc = 1; proc < CPUS; proc++) |
714 | for (proc = 1; proc < CPUS; proc++) |
673 | thread[proc]. |
715 | thread[proc].terminate = 1; |
674 | while (smp_threads); |
716 | while (smp_threads); |
675 | smp_idle = 0; |
- | |
676 | smp_split = 0; |
717 | smp_split = 0; |
677 | } |
718 | } |
678 | program_end_time = ReadClock(); |
719 | program_end_time = ReadClock(); |
679 | search_move = 0; |
720 | search_move = 0; |
680 | if (quit) |
721 | if (quit) |