Rev 108 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 108 | Rev 154 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | #include "chess.h" |
1 | #include "chess.h" |
2 | #include "data.h" |
2 | #include "data.h" |
- | 3 | #if defined(SYZYGY) |
|
- | 4 | # include "tbprobe.h" |
|
- | 5 | #endif |
|
3 | /* last modified |
6 | /* last modified 08/03/16 */ |
4 | /* |
7 | /* |
5 | ******************************************************************************* |
8 | ******************************************************************************* |
6 | * * |
9 | * * |
7 | * Search() is the recursive routine used to implement the alpha/beta * |
10 | * Search() is the recursive routine used to implement the alpha/beta * |
8 | * negamax search (similar to minimax but simpler to code.) Search() is * |
11 | * negamax search (similar to minimax but simpler to code.) Search() is * |
Line 67... | Line 70... | ||
67 | * * |
70 | * * |
68 | ************************************************************ |
71 | ************************************************************ |
69 | */ |
72 | */ |
70 | if (ply > 1) { |
73 | if (ply > 1) { |
71 | if ((repeat = Repeat(tree, ply))) { |
74 | if ((repeat = Repeat(tree, ply))) { |
72 | if (repeat == |
75 | if (repeat == 2 || !in_check) { |
73 | value = DrawScore(wtm); |
76 | value = DrawScore(wtm); |
74 | if (value < beta) |
77 | if (value < beta) |
75 | SavePV(tree, ply, |
78 | SavePV(tree, ply, repeat); |
76 | #if defined(TRACE) |
79 | #if defined(TRACE) |
77 | if (ply <= trace_level) |
80 | if (ply <= trace_level) |
78 | printf("draw by |
81 | printf("draw by %s detected, ply=%d.\n", |
- | 82 | (repeat == 3) ? "50-move" : "repetition", ply); |
|
79 | #endif |
83 | #endif |
80 | return value; |
84 | return value; |
81 | } |
85 | } |
82 | } |
86 | } |
83 | /* |
87 | /* |
Line 132... | Line 136... | ||
132 | /* |
136 | /* |
133 | ************************************************************ |
137 | ************************************************************ |
134 | * * |
138 | * * |
135 | * EGTBs. Now it's time to try a probe into the endgame * |
139 | * EGTBs. Now it's time to try a probe into the endgame * |
136 | * tablebase files. This is done if we notice that there * |
140 | * tablebase files. This is done if we notice that there * |
137 | * are 6 or fewer pieces left on the board AND the move |
141 | * are 6 or fewer pieces left on the board AND the 50 move * |
- | 142 | * counter is zero which enables probing the WDL EGTBs * |
|
138 | * |
143 | * correctly. Probing after a capture won't work as it is * |
139 | * |
144 | * possible that there is a necessary pawn push here and * |
140 | * |
145 | * there to reset the 50 move counter, otherwise we could * |
141 | * |
146 | * think we were following a winning path but heading to a * |
142 | * |
147 | * draw. * |
143 | * |
148 | * * |
144 | * This is another way to get out of the search quickly, * |
149 | * This is another way to get out of the search quickly, * |
145 | * but not as quickly as the previous steps since this can * |
150 | * but not as quickly as the previous steps since this can * |
146 | * result in an I/O operation. * |
151 | * result in an I/O operation. * |
147 | * * |
152 | * * |
148 | * Note that in "swindle mode" this can be turned off by * |
153 | * Note that in "swindle mode" this can be turned off by * |
Line 151... | Line 156... | ||
151 | * that lead to a draw and we want to play the move that * |
156 | * that lead to a draw and we want to play the move that * |
152 | * makes the draw more difficult to reach by the opponent * |
157 | * makes the draw more difficult to reach by the opponent * |
153 | * to give him a chance to make a mistake. * |
158 | * to give him a chance to make a mistake. * |
154 | * * |
159 | * * |
155 | * Another special case is that we slightly fudge the * |
160 | * Another special case is that we slightly fudge the * |
156 | * score for draws. |
161 | * score for draws. The scores are -0.03 for a "blessed * |
- | 162 | * loss", 0.0 for a pure draw, and +0.03 for a "cursed * |
|
157 | * |
163 | * win". These are then modified by adding 0.01 if the * |
158 | * |
164 | * side on move is ahead in material, and subtracting 0.01 * |
- | 165 | * if the side on move is behind material. This creates * |
|
- | 166 | * the following inequality: * |
|
159 | * |
167 | * * |
- | 168 | * BL- < BL= < BL+ < D- < D= < D+ < CW- < CW= <CW+ * |
|
160 | * |
169 | * * |
- | 170 | * Where BL=blessed loss, D = draw, and CW = cursed win, * |
|
- | 171 | * and - means behind in material, = means equal material, * |
|
161 | * |
172 | * and + means ahead in material. * |
162 | * * |
173 | * * |
163 | ************************************************************ |
174 | ************************************************************ |
164 | */ |
175 | */ |
165 | #if |
176 | #if defined(SYZYGY) |
166 | if (depth > EGTB_depth && TotalAllPieces <= EGTB_use && |
177 | if (depth > EGTB_depth && TotalAllPieces <= EGTB_use && |
167 | !Castle(ply, white) && !Castle(ply, black) && |
178 | !Castle(ply, white) && !Castle(ply, black) && Reversible(ply) == 0) { |
168 | (Captured(tree->curmv[ply - 1]) || ply < 3)) { |
- | |
169 | int |
179 | int tb_result; |
170 | 180 | ||
171 | tree->egtb_probes++; |
181 | tree->egtb_probes++; |
- | 182 | tb_result = |
|
- | 183 | tb_probe_wdl(Occupied(white), Occupied(black), |
|
- | 184 | Kings(white) | Kings(black), Queens(white) | Queens(black), |
|
- | 185 | Rooks(white) | Rooks(black), Bishops(white) | Bishops(black), |
|
- | 186 | Knights(white) | Knights(black), Pawns(white) | Pawns(black), |
|
- | 187 | Reversible(ply), 0, EnPassant(ply), wtm, HashKey); |
|
172 | if ( |
188 | if (tb_result != TB_RESULT_FAILED) { |
173 | tree->egtb_hits++; |
189 | tree->egtb_hits++; |
- | 190 | switch (tb_result) { |
|
- | 191 | case TB_LOSS: |
|
174 | alpha = |
192 | alpha = -TBWIN; |
175 |
|
193 | break; |
- | 194 | case TB_BLESSED_LOSS: |
|
176 |
|
195 | alpha = -3; |
- | 196 | break; |
|
- | 197 | case TB_DRAW: |
|
177 |
|
198 | alpha = 0; |
- | 199 | break; |
|
- | 200 | case TB_CURSED_WIN: |
|
- | 201 | alpha = 3; |
|
- | 202 | break; |
|
- | 203 | case TB_WIN: |
|
178 |
|
204 | alpha = TBWIN; |
- | 205 | break; |
|
- | 206 | } |
|
- | 207 | if (tb_result != TB_LOSS && tb_result != TB_WIN) { |
|
179 | if (MaterialSTM(wtm) > 0) |
208 | if (MaterialSTM(wtm) > 0) |
180 | alpha += 1; |
209 | alpha += 1; |
181 | else if (MaterialSTM(wtm) < 0) |
210 | else if (MaterialSTM(wtm) < 0) |
182 | alpha -= 1; |
211 | alpha -= 1; |
183 | } |
212 | } |
184 | if (alpha < beta) |
213 | if (alpha < beta) |
185 | SavePV(tree, ply, |
214 | SavePV(tree, ply, 4); |
186 | return alpha; |
215 | return alpha; |
187 | } |
216 | } |
188 | } |
217 | } |
189 | #endif |
218 | #endif |
190 | /* |
219 | /* |
Line 227... | Line 256... | ||
227 | ************************************************************ |
256 | ************************************************************ |
228 | */ |
257 | */ |
229 | 258 | ||
230 | tree->last[ply] = tree->last[ply - 1]; |
259 | tree->last[ply] = tree->last[ply - 1]; |
231 | n_depth = (TotalPieces(wtm, occupied) > 9 || n_root_moves > 17 || |
260 | n_depth = (TotalPieces(wtm, occupied) > 9 || n_root_moves > 17 || |
232 |
|
261 | depth > 3) ? 1 : 3; |
233 | if (do_null && !pv_node && depth > n_depth && !in_check && |
262 | if (do_null && !pv_node && depth > n_depth && !in_check && |
234 | TotalPieces(wtm, occupied)) { |
263 | TotalPieces(wtm, occupied)) { |
235 | uint64_t save_hash_key; |
264 | uint64_t save_hash_key; |
236 | int R = null_depth + depth / null_divisor; |
265 | int R = null_depth + depth / null_divisor; |
237 | 266 | ||
Line 315... | Line 344... | ||
315 | SearchMoveList(tree, ply, depth, wtm, alpha, beta, searched, in_check, |
344 | SearchMoveList(tree, ply, depth, wtm, alpha, beta, searched, in_check, |
316 | repeat, serial); |
345 | repeat, serial); |
317 | return value; |
346 | return value; |
318 | } |
347 | } |
319 | 348 | ||
320 | /* last modified |
349 | /* last modified 08/03/16 */ |
321 | /* |
350 | /* |
322 | ******************************************************************************* |
351 | ******************************************************************************* |
323 | * * |
352 | * * |
324 | * SearchMoveList() is the recursive routine used to implement the main * |
353 | * SearchMoveList() is the recursive routine used to implement the main * |
325 | * search loop. This code is responsible for iterating through the move * |
354 | * search loop. This code is responsible for iterating through the move * |
Line 349... | Line 378... | ||
349 | */ |
378 | */ |
350 | int SearchMoveList(TREE * RESTRICT tree, int ply, int depth, int wtm, |
379 | int SearchMoveList(TREE * RESTRICT tree, int ply, int depth, int wtm, |
351 | int alpha, int beta, int searched[], int in_check, int repeat, int mode) { |
380 | int alpha, int beta, int searched[], int in_check, int repeat, int mode) { |
352 | TREE *current; |
381 | TREE *current; |
353 | int extend, reduce, check, original_alpha = alpha, t_beta; |
382 | int extend, reduce, check, original_alpha = alpha, t_beta; |
354 | int i, value = 0, pv_node = alpha != beta - 1, |
383 | int i, j, value = 0, pv_node = alpha != beta - 1, search_result, order; |
355 | int moves_done = 0 |
384 | int moves_done = 0, bestmove, type; |
356 | 385 | ||
357 | /* |
386 | /* |
358 | ************************************************************ |
387 | ************************************************************ |
359 | * * |
388 | * * |
360 | * Basic initialization before we begin the loop through * |
389 | * Basic initialization before we begin the loop through * |
Line 404... | Line 433... | ||
404 | if (ply == 1 && moves_done == 1 && alpha == original_alpha && |
433 | if (ply == 1 && moves_done == 1 && alpha == original_alpha && |
405 | mode == serial) |
434 | mode == serial) |
406 | break; |
435 | break; |
407 | if (mode == parallel) |
436 | if (mode == parallel) |
408 | Lock(current->lock); |
437 | Lock(current->lock); |
409 | order = (ply > 1) ? NextMove(current, ply, depth, wtm, in_check) |
438 | order = (ply > 1) ? NextMove(current, ply, depth, wtm, in_check) |
410 | NextRootMove(current, tree, wtm); |
439 | : NextRootMove(current, tree, wtm); |
411 | phase = current->phase[ply]; |
- | |
412 | if (mode == parallel) { |
440 | if (mode == parallel) { |
413 | tree->curmv[ply] = |
441 | tree->curmv[ply] = current->curmv[ply]; |
414 | Unlock(current->lock); |
442 | Unlock(current->lock); |
415 | } |
443 | } |
416 | if (!order) |
444 | if (!order) |
417 | break; |
445 | break; |
418 | #if defined(TRACE) |
446 | #if defined(TRACE) |
419 | if (ply <= trace_level) |
447 | if (ply <= trace_level) |
420 | Trace(tree, ply, depth, wtm, alpha, beta, "SearchMoveList", mode |
448 | Trace(tree, ply, depth, wtm, alpha, beta, "SearchMoveList", mode, |
421 | order); |
449 | current->phase[ply], order); |
422 | #endif |
450 | #endif |
423 | MakeMove(tree, ply, wtm, tree->curmv[ply]); |
451 | MakeMove(tree, ply, wtm, tree->curmv[ply]); |
424 | tree->nodes_searched++; |
452 | tree->nodes_searched++; |
425 |
|
453 | search_result = ILLEGAL; |
426 | if (in_check || !Check(wtm)) |
454 | if (in_check || !Check(wtm)) |
427 | do { |
455 | do { |
428 | searched[0]++; |
456 | searched[0]++; |
429 | moves_done++; |
457 | moves_done++; |
430 |
|
458 | search_result = LEGAL; |
431 | searched[searched[0]] = tree->curmv[ply]; |
459 | searched[searched[0]] = tree->curmv[ply]; |
432 | /* |
460 | /* |
433 | ************************************************************ |
461 | ************************************************************ |
434 | * * |
462 | * * |
435 | * Check. If the move to be made checks the opponent, * |
463 | * Check. If the move to be made checks the opponent, * |
Line 496... | Line 524... | ||
496 | * * |
524 | * * |
497 | * (2) move has not already been flagged for a search * |
525 | * (2) move has not already been flagged for a search * |
498 | * extension. * |
526 | * extension. * |
499 | * * |
527 | * * |
500 | * (3) this is not the first move at this ply. * |
528 | * (3) this is not the first move at this ply. * |
501 | * * |
- | |
502 | * (4) we are in the REMAINING phase, which means that a * |
- | |
503 | * cutoff is not very likely. * |
- | |
504 | * * |
529 | * * |
505 | ************************************************************ |
530 | ************************************************************ |
506 | */ |
531 | */ |
507 | if (!in_check && !extend |
532 | if (!in_check && (!extend || !pv_node) && order > 1 && |
508 | !(PawnPush(wtm, tree->curmv[ply]))) { |
533 | !(PawnPush(wtm, tree->curmv[ply]))) { |
509 | if ( |
534 | if (depth < FP_depth && !check && |
510 | MaterialSTM(wtm) + |
535 | MaterialSTM(wtm) + FP_margin[depth] <= alpha && !pv_node) { |
511 | tree->moves_fpruned++; |
536 | tree->moves_fpruned++; |
512 | break; |
537 | break; |
513 | } |
538 | } |
514 | /* |
539 | /* |
515 | ************************************************************ |
540 | ************************************************************ |
Line 521... | Line 546... | ||
521 | * significant number of moves at a ply, it becomes less * |
546 | * significant number of moves at a ply, it becomes less * |
522 | * and less likely that any of the moves left will produce * |
547 | * and less likely that any of the moves left will produce * |
523 | * a cutoff. If the move appears to be simple (not a * |
548 | * a cutoff. If the move appears to be simple (not a * |
524 | * check, etc) then we simply skip it, once the move count * |
549 | * check, etc) then we simply skip it, once the move count * |
525 | * has been satisfied. At present, we only do this in the * |
550 | * has been satisfied. At present, we only do this in the * |
526 | * last |
551 | * last 16 plies although this might be changed in the * |
527 | * future. |
552 | * future. If you look at the LMP array after it has been * |
- | 553 | * initialized, you will notice that it is unlikely that * |
|
- | 554 | * LMP can be triggered much beyond depth 8 as you have to * |
|
- | 555 | * have a BUNCH of moves to search to reach those limits. * |
|
528 | * * |
556 | * * |
529 | ************************************************************ |
557 | ************************************************************ |
530 | */ |
558 | */ |
531 | if ( |
559 | if (order > LMP[depth] && depth < LMP_depth && !pv_node && !check && |
532 | !CaptureOrPromote(tree->curmv[ply]) |
560 | alpha > -MATE + 300 && !CaptureOrPromote(tree->curmv[ply])) { |
533 | order > movecnt_pruning[depth]) { |
- | |
534 | tree->moves_mpruned++; |
561 | tree->moves_mpruned++; |
535 | break; |
562 | break; |
536 | } |
563 | } |
537 | /* |
564 | /* |
538 | ************************************************************ |
565 | ************************************************************ |
Line 549... | Line 576... | ||
549 | * formula is user-settable via the "lmr" command. * |
576 | * formula is user-settable via the "lmr" command. * |
550 | * * |
577 | * * |
551 | ************************************************************ |
578 | ************************************************************ |
552 | */ |
579 | */ |
553 | reduce = LMR[Min(depth, 31)][Min(order, 63)]; |
580 | reduce = LMR[Min(depth, 31)][Min(order, 63)]; |
- | 581 | if (reduce && (pv_node || extend)) |
|
- | 582 | reduce--; |
|
554 | tree->LMR_done[reduce]++; |
583 | tree->LMR_done[reduce]++; |
555 | } |
584 | } |
556 | /* |
585 | /* |
557 | ************************************************************ |
586 | ************************************************************ |
558 | * * |
587 | * * |
Line 563... | Line 592... | ||
563 | * called Unmake(). This cleaned up the exit from search * |
592 | * called Unmake(). This cleaned up the exit from search * |
564 | * and makes it easier to understand when there is only * |
593 | * and makes it easier to understand when there is only * |
565 | * one point where this is done, without needing multiple * |
594 | * one point where this is done, without needing multiple * |
566 | * Unmake() calls when there are different exit points. * |
595 | * Unmake() calls when there are different exit points. * |
567 | * * |
596 | * * |
568 | ************************************************************ |
597 | ************************************************************** |
569 | */ |
598 | */ |
570 | value = |
599 | value = |
571 | SearchMove(tree, ply, depth, wtm, alpha, t_beta, beta, extend, |
600 | SearchMove(tree, ply, depth, wtm, alpha, t_beta, beta, extend, |
572 | reduce, check); |
601 | reduce, check); |
573 | if (value > alpha) { |
602 | if (value > alpha) { |
574 |
|
603 | search_result = IN_WINDOW; |
575 | if (value >= beta) |
604 | if (value >= beta) |
576 |
|
605 | search_result = FAIL_HIGH; |
577 | if (mode == parallel && ply == 1) |
606 | if (mode == parallel && ply == 1) |
578 |
|
607 | search_result = FAIL_HIGH; |
579 | } |
608 | } |
580 | } while (0); |
609 | } while (0); |
581 | UnmakeMove(tree, ply, wtm, tree->curmv[ply]); |
610 | UnmakeMove(tree, ply, wtm, tree->curmv[ply]); |
582 | if (abort_search || tree->stop) |
611 | if (abort_search || tree->stop) |
583 | break; |
612 | break; |
Line 587... | Line 616... | ||
587 | * Test 1. When we get here, we have made a move, * |
616 | * Test 1. When we get here, we have made a move, * |
588 | * searched it (and re-searched if necessary/appropriate), * |
617 | * searched it (and re-searched if necessary/appropriate), * |
589 | * and the move has been unmade so that the board is in a * |
618 | * and the move has been unmade so that the board is in a * |
590 | * correct state. * |
619 | * correct state. * |
591 | * * |
620 | * * |
592 | * If |
621 | * If search_result = FAIL_HIGH, the search failed high. * |
593 | * first thing to handle is the case where we are at |
622 | * The first thing to handle is the case where we are at * |
594 | * ply=1, which is a special case. If we are going to * |
623 | * ply=1, which is a special case. If we are going to * |
595 | * fail high here and terminate the search immediately, we * |
624 | * fail high here and terminate the search immediately, we * |
596 | * need to build the fail-high PV to back up to Iterate() * |
625 | * need to build the fail-high PV to back up to Iterate() * |
597 | * so it will produce the correct output and widen the * |
626 | * so it will produce the correct output and widen the * |
598 | * alpha/beta window. * |
627 | * alpha/beta window. * |
Line 608... | Line 637... | ||
608 | * trans/ref table for future use if we happen to reach * |
637 | * trans/ref table for future use if we happen to reach * |
609 | * this position again. * |
638 | * this position again. * |
610 | * * |
639 | * * |
611 | ************************************************************ |
640 | ************************************************************ |
612 | */ |
641 | */ |
613 | if ( |
642 | if (search_result == FAIL_HIGH) { |
614 | if (ply == 1) { |
643 | if (ply == 1) { |
615 | if (!tree->stop) { |
644 | if (!tree->stop) { |
616 | tree->pv[1].path[1] = tree->curmv[1]; |
645 | tree->pv[1].path[1] = tree->curmv[1]; |
617 | tree->pv[1].pathl = 2; |
646 | tree->pv[1].pathl = 2; |
618 | tree->pv[1].pathh = 0; |
647 | tree->pv[1].pathh = 0; |
Line 626... | Line 655... | ||
626 | Lock(tree->parent->lock); |
655 | Lock(tree->parent->lock); |
627 | if (!tree->stop) { |
656 | if (!tree->stop) { |
628 | int proc; |
657 | int proc; |
629 | 658 | ||
630 | parallel_aborts++; |
659 | parallel_aborts++; |
631 | for (proc = 0; proc < |
660 | for (proc = 0; proc < smp_max_threads; proc++) |
632 | if (tree->parent->siblings[proc] && proc != tree->thread_id) |
661 | if (tree->parent->siblings[proc] && proc != tree->thread_id) |
633 | ThreadStop(tree->parent->siblings[proc]); |
662 | ThreadStop(tree->parent->siblings[proc]); |
634 | } |
663 | } |
635 | Unlock(tree->parent->lock); |
664 | Unlock(tree->parent->lock); |
636 | Unlock(lock_smp); |
665 | Unlock(lock_smp); |
637 | return |
666 | return beta; |
638 | } |
667 | } |
639 | #endif |
668 | #endif |
640 | tree->fail_highs++; |
669 | tree->fail_highs++; |
641 | if (order == 1) |
670 | if (order == 1) |
642 | tree->fail_high_first_move++; |
671 | tree->fail_high_first_move++; |
Line 644... | Line 673... | ||
644 | History(tree, ply, depth, wtm, tree->curmv[ply], searched); |
673 | History(tree, ply, depth, wtm, tree->curmv[ply], searched); |
645 | return beta; |
674 | return beta; |
646 | /* |
675 | /* |
647 | ************************************************************ |
676 | ************************************************************ |
648 | * * |
677 | * * |
649 | * Test 2. If |
678 | * Test 2. If search_result = IN_WINDOW, this is a search * |
650 | * improved alpha without failing high. We simply |
679 | * that improved alpha without failing high. We simply * |
651 | * alpha and continue searching moves. |
680 | * update alpha and continue searching moves. * |
652 | * * |
681 | * * |
653 | * Special case: If ply = 1 in a normal search, we have * |
682 | * Special case: If ply = 1 in a normal search, we have * |
654 | * a best move and score that just changed. We need to * |
683 | * a best move and score that just changed. We need to * |
655 | * update the root move list by adding the PV and the * |
684 | * update the root move list by adding the PV and the * |
656 | * score, and then we look to make sure this new "best * |
685 | * score, and then we look to make sure this new "best * |
657 | * move" is not actually worse than the best we have found * |
686 | * move" is not actually worse than the best we have found * |
658 | * so far this iteration. If it is worse, we restore the * |
687 | * so far this iteration. If it is worse, we restore the * |
659 | * best move and score from the real best move so our * |
688 | * best move and score from the real best move so our * |
660 | * search window won't be out of whack, which would let * |
689 | * search window won't be out of whack, which would let * |
661 | * moves with scores in between this bad move and the best * |
690 | * moves with scores in between this bad move and the best * |
662 | * move fail high, cause re-searches, and waste time. |
691 | * move fail high, cause re-searches, and waste time. We * |
- | 692 | * also need to restore the root move list so that the * |
|
- | 693 | * best move (the one we just used to replace the move * |
|
- | 694 | * with a worse score) is first so it is searched first on * |
|
- | 695 | * the next iteration. * |
|
663 | * * |
696 | * * |
664 | * If this is ply = 1, we display the PV to keep the user * |
697 | * If this is ply = 1, we display the PV to keep the user * |
665 | * informed. * |
698 | * informed. * |
666 | * * |
699 | * * |
667 | ************************************************************ |
700 | ************************************************************ |
668 | */ |
701 | */ |
669 | } else if ( |
702 | } else if (search_result == IN_WINDOW) { |
670 | alpha = value; |
703 | alpha = value; |
671 | if (ply == 1 && mode == serial) { |
704 | if (ply == 1 && mode == serial) { |
- | 705 | int best; |
|
- | 706 | ||
- | 707 | // |
|
- | 708 | // update path/score for this move |
|
- | 709 | // |
|
672 | tree->pv[1].pathv = value; |
710 | tree->pv[1].pathv = value; |
673 | tree->pv[0] = tree->pv[1]; |
711 | tree->pv[0] = tree->pv[1]; |
674 | for ( |
712 | for (best = 0; best < n_root_moves; best++) |
675 | if (root_moves[ |
713 | if (root_moves[best].move == tree->pv[1].path[1]) { |
676 | root_moves[ |
714 | root_moves[best].path = tree->pv[1]; |
677 | root_moves[ |
715 | root_moves[best].path.pathv = alpha; |
- | 716 | break; |
|
678 | } |
717 | } |
- | 718 | // |
|
- | 719 | // if this move is not #1 in root list, move it there |
|
- | 720 | // |
|
- | 721 | if (best != 0) { |
|
- | 722 | ROOT_MOVE t; |
|
- | 723 | t = root_moves[best]; |
|
- | 724 | for (i = best; i > 0; i--) |
|
- | 725 | root_moves[i] = root_moves[i - 1]; |
|
- | 726 | root_moves[0] = t; |
|
- | 727 | } |
|
- | 728 | // |
|
- | 729 | // if a better score has already been found then move that |
|
- | 730 | // move to the front of the list and update alpha bound. |
|
- | 731 | // |
|
679 | for (i = 0; i < n_root_moves; i++) |
732 | for (i = 0; i < n_root_moves; i++) { |
680 | if (value < root_moves[i].path.pathv) { |
733 | if (value <= root_moves[i].path.pathv) { |
- | 734 | ROOT_MOVE t; |
|
681 | value = root_moves[i].path.pathv; |
735 | value = root_moves[i].path.pathv; |
682 | alpha = value; |
736 | alpha = value; |
683 | tree->pv[0] = root_moves[i].path; |
737 | tree->pv[0] = root_moves[i].path; |
684 | tree->pv[1] = tree->pv[0]; |
738 | tree->pv[1] = tree->pv[0]; |
- | 739 | t = root_moves[i]; |
|
- | 740 | for (j = i; j > 0; j--) |
|
- | 741 | root_moves[j] = root_moves[j - 1]; |
|
- | 742 | root_moves[0] = t; |
|
685 | } |
743 | } |
- | 744 | } |
|
686 | Output(tree); |
745 | Output(tree); |
687 | failhi_delta = 16; |
746 | failhi_delta = 16; |
688 | faillo_delta = 16; |
747 | faillo_delta = 16; |
689 | } |
748 | } |
690 | } |
749 | } |
691 | /* |
750 | /* |
692 | ************************************************************ |
751 | ************************************************************ |
693 | * * |
752 | * * |
694 | * Test 3. If |
753 | * Test 3. If search_result = ILLEGAL, this search was * |
695 | * |
754 | * given an illegal move and no search was done, we skip * |
696 | * updating and simply select the next move to search. |
755 | * any updating and simply select the next move to search. * |
697 | * * |
756 | * * |
698 | ************************************************************ |
757 | ************************************************************ |
699 | */ |
758 | */ |
700 | else if ( |
759 | else if (search_result == ILLEGAL) |
701 | continue; |
760 | continue; |
702 | t_beta = alpha + 1; |
761 | t_beta = alpha + 1; |
703 | /* |
762 | /* |
704 | ************************************************************ |
763 | ************************************************************ |
705 | * * |
764 | * * |
Line 754... | Line 813... | ||
754 | * at the same time. We allow multiple threads to split * |
813 | * at the same time. We allow multiple threads to split * |
755 | * at the same time, but then the idle threads will choose * |
814 | * at the same time, but then the idle threads will choose * |
756 | * to join the thread with the most attractive split point * |
815 | * to join the thread with the most attractive split point * |
757 | * rather than just taking pot-luck. The only limitation * |
816 | * rather than just taking pot-luck. The only limitation * |
758 | * on a thread adding a split point here is that if the * |
817 | * on a thread adding a split point here is that if the * |
759 | * thread already has enough joinable split points |
818 | * thread already has enough joinable split points that * |
760 | * not been joined yet, we do not incur the overhead |
819 | * have not been joined yet, we do not incur the overhead * |
761 | * creating another split point until the |
820 | * of creating another split point until one of the * |
- | 821 | * existing split points has been completed or a thread * |
|
762 | * |
822 | * joins at at one of those available split points. * |
763 | * * |
823 | * * |
764 | * We do not lock anything here, as the split operation * |
824 | * We do not lock anything here, as the split operation * |
765 | * only affects thread-local data. When the split is done * |
825 | * only affects thread-local data. When the split is done * |
766 | * then the ThreadJoin() function will acquire the lock * |
826 | * then the ThreadJoin() function will acquire the lock * |
767 | * needed to avoid race conditions during the join op- * |
827 | * needed to avoid race conditions during the join op- * |
Line 842... | Line 902... | ||
842 | original_alpha) ? tree->hash_move[ply] : tree->pv[ply].path[ply]; |
902 | original_alpha) ? tree->hash_move[ply] : tree->pv[ply].path[ply]; |
843 | type = (alpha == original_alpha) ? UPPER : EXACT; |
903 | type = (alpha == original_alpha) ? UPPER : EXACT; |
844 | if (repeat == 2 && alpha != -(MATE - ply - 1)) { |
904 | if (repeat == 2 && alpha != -(MATE - ply - 1)) { |
845 | value = DrawScore(wtm); |
905 | value = DrawScore(wtm); |
846 | if (value < beta) |
906 | if (value < beta) |
847 | SavePV(tree, ply, |
907 | SavePV(tree, ply, 3); |
848 | #if defined(TRACE) |
908 | #if defined(TRACE) |
849 | if (ply <= trace_level) |
909 | if (ply <= trace_level) |
850 | printf("draw by 50 move rule detected, ply=%d.\n", ply); |
910 | printf("draw by 50 move rule detected, ply=%d.\n", ply); |
851 | #endif |
911 | #endif |
852 | return value; |
912 | return value; |
Line 857... | Line 917... | ||
857 | HashStore(tree, ply, depth, wtm, type, alpha, bestmove); |
917 | HashStore(tree, ply, depth, wtm, type, alpha, bestmove); |
858 | return alpha; |
918 | return alpha; |
859 | } |
919 | } |
860 | } |
920 | } |
861 | 921 | ||
862 | /* last modified |
922 | /* last modified 08/03/16 */ |
863 | /* |
923 | /* |
864 | ******************************************************************************* |
924 | ******************************************************************************* |
865 | * * |
925 | * * |
866 | * SearchMove() implements the PVS search and returns the value. We do a * |
926 | * SearchMove() implements the PVS search and returns the value. We do a * |
867 | * null-window search with the window (alpha, t_beta) and if that fails high * |
927 | * null-window search with the window (alpha, t_beta) and if that fails high * |