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 * |