Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 05/08/14 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   Search() is the recursive routine used to implement the alpha/beta        *
  8.  *   negamax search (similar to minimax but simpler to code.)  Search() is     *
  9.  *   called whenever there is "depth" remaining so that all moves are subject  *
  10.  *   to searching.  Search() recursively calls itself so long as there is at   *
  11.  *   least one ply of depth left, otherwise it calls Quiesce() instead.        *
  12.  *                                                                             *
  13.  *******************************************************************************
  14.  */
  15. int Search(TREE * RESTRICT tree, int alpha, int beta, int side, int depth,
  16.     int ply, int do_null) {
  17.   ROOT_MOVE temp_rm;
  18.   uint64_t start_nodes = tree->nodes_searched;
  19.   int first_tried = 0, moves_searched = 0, repeat = 0;
  20.   int original_alpha = alpha, value = 0, t_beta = beta;
  21.   int extend, reduce, max_reduce, i;
  22.   int pv_node = alpha != beta - 1;
  23.  
  24. /*
  25.  ************************************************************
  26.  *                                                          *
  27.  *  Step 1.  Check to see if we have searched enough nodes  *
  28.  *  that it is time to peek at how much time has been used, *
  29.  *  or if is time to check for operator keyboard input.     *
  30.  *  This is usually enough nodes to force a time/input      *
  31.  *  check about once per second, except when the target     *
  32.  *  time per move is very small, in which case we try to    *
  33.  *  check the time more frequently.                         *
  34.  *                                                          *
  35.  *  Note that we check input or time-out in thread 0.  This *
  36.  *  makes the code simpler and eliminates some problematic  *
  37.  *  race conditions.                                        *
  38.  *                                                          *
  39.  ************************************************************
  40.  */
  41. #if defined(NODES)
  42.   if (--temp_search_nodes <= 0) {
  43.     abort_search = 1;
  44.     return 0;
  45.   }
  46. #endif
  47.   if (tree->thread_id == 0) {
  48.     if (--next_time_check <= 0) {
  49.       next_time_check = nodes_between_time_checks;
  50.       if (TimeCheck(tree, 1)) {
  51.         abort_search = 1;
  52.         return 0;
  53.       }
  54.       if (CheckInput()) {
  55.         Interrupt(ply);
  56.         if (abort_search)
  57.           return 0;
  58.       }
  59.     }
  60.   }
  61.   if (ply >= MAXPLY - 1)
  62.     return beta;
  63. /*
  64.  ************************************************************
  65.  *                                                          *
  66.  *  Step 2.  Check for draw by repetition, which includes   *
  67.  *  50 move draws also.  This is the quickest way to get    *
  68.  *  out of further searching, with minimal effort.  This    *
  69.  *  and the next two steps are skipped for moves at the     *
  70.  *  root (ply = 1).                                         *
  71.  *                                                          *
  72.  ************************************************************
  73.  */
  74.   if (ply > 1) {
  75.     if ((repeat = Repeat(tree, ply))) {
  76.       value = DrawScore(side);
  77.       if (value < beta)
  78.         SavePV(tree, ply, 0);
  79. #if defined(TRACE)
  80.       if (ply <= trace_level)
  81.         printf("draw by repetition detected, ply=%d.\n", ply);
  82. #endif
  83.       return value;
  84.     }
  85. /*
  86.  ************************************************************
  87.  *                                                          *
  88.  *  Step 3.  Check the transposition/refutation (hash)      *
  89.  *  table to see if we have searched this position          *
  90.  *  previously and still have the results available.  We    *
  91.  *  might get a real score, or a bound, or perhaps only a   *
  92.  *  good move to try first.  The possible results are:      *
  93.  *                                                          *
  94.  *  1. HashProbe() returns "HASH_HIT".  This terminates     *
  95.  *  the search instantly and we simply return the value     *
  96.  *  found in the hash table.  This value is simply the      *
  97.  *  value we found when we did a real search in this        *
  98.  *  position previously, and HashProbe() verifies that the  *
  99.  *  value is useful based on draft and current bounds.      *
  100.  *                                                          *
  101.  *  2. HashProbe() returns "AVOID_NULL_MOVE" which means    *
  102.  *  the hashed score/bound was no good, but it indicated    *
  103.  *  that trying a null-move in this position would be a     *
  104.  *  waste of time since it will likely fail low, not high.  *
  105.  *                                                          *
  106.  *  3. HashProbe() returns "HASH_MISS" when forces us to    *
  107.  *  do a normal search to resolve this node.                *
  108.  *                                                          *
  109.  ************************************************************
  110.  */
  111.     switch (HashProbe(tree, ply, depth, side, alpha, beta, &value)) {
  112.       case HASH_HIT:
  113.         return value;
  114.       case AVOID_NULL_MOVE:
  115.         do_null = 0;
  116.       case HASH_MISS:
  117.         break;
  118.     }
  119. /*
  120.  ************************************************************
  121.  *                                                          *
  122.  *  Step 4.  Now it's time to try a probe into the endgame  *
  123.  *  tablebase files.  This is done if we notice that there  *
  124.  *  are 6 or fewer pieces left on the board.  EGTB_use      *
  125.  *  tells us how many pieces to probe on.  Note that this   *
  126.  *  can be zero when trying to swindle the opponent, so     *
  127.  *  that no probes are done since we know it is a draw.     *
  128.  *  This is another way to get out of the search quickly,   *
  129.  *  but not as quickly as the previous steps since this can *
  130.  *  result in an I/O operation.                             *
  131.  *                                                          *
  132.  *  Note that in "swindle mode" this can be turned off by   *
  133.  *  Iterate() setting "EGTB_use = 0" so that we won't probe *
  134.  *  the EGTBs since we are searching only the root moves    *
  135.  *  that lead to a draw and we want to play the move that   *
  136.  *  makes the draw more difficult to reach by the opponent  *
  137.  *  to give him a chance to make a mistake.                 *
  138.  *                                                          *
  139.  *  Another special case is that we slightly fudge the      *
  140.  *  score for draws.  In a normal circumstance, draw=0.00   *
  141.  *  since it is "equal".  However, here we add 0.01 if      *
  142.  *  white has more material, or subtract 0.01 if black has  *
  143.  *  more material, since in a drawn KRP vs KR we would      *
  144.  *  prefer to have the KRP side since the opponent can make *
  145.  *  a mistake and convert the draw to a loss.               *
  146.  *                                                          *
  147.  ************************************************************
  148.  */
  149. #if !defined(NOEGTB)
  150.     if (depth > 6 && TotalAllPieces <= EGTB_use &&
  151.         Castle(ply, white) + Castle(ply, black) == 0 &&
  152.         (CaptureOrPromote(tree->curmv[ply - 1]) || ply < 3)) {
  153.       int egtb_value;
  154.  
  155.       tree->egtb_probes++;
  156.       if (EGTBProbe(tree, ply, side, &egtb_value)) {
  157.         tree->egtb_probes_successful++;
  158.         alpha = egtb_value;
  159.         if (MateScore(alpha))
  160.           alpha += (alpha > 0) ? -ply + 1 : ply;
  161.         else if (alpha == 0) {
  162.           alpha = DrawScore(side);
  163.           if (Material > 0)
  164.             alpha += (side) ? 1 : -1;
  165.           else if (Material < 0)
  166.             alpha -= (side) ? 1 : -1;
  167.         }
  168.         if (alpha < beta)
  169.           SavePV(tree, ply, 2);
  170.         return alpha;
  171.       }
  172.     }
  173. #endif
  174. /*
  175.  ************************************************************
  176.  *                                                          *
  177.  *  Step 5.  We now know there is no quick way to get out   *
  178.  *  of here, which leaves one more possibility, although it *
  179.  *  does require s search, but to a reduced depth.  We      *
  180.  *  try a null move to see if we can get a quick cutoff     *
  181.  *  with only a little work.  This operates as follows.     *
  182.  *  Instead of making a legal move, the side on move passes *
  183.  *  and does nothing.  The resulting position is searched   *
  184.  *  to a shallower depth than normal (usually 3 plies less  *
  185.  *  but settable by the user.) This will result in a cutoff *
  186.  *  if our position is very good, but it produces the       *
  187.  *  cutoff much quicker since the search is far shallower   *
  188.  *  than a normal search that would also be likely to fail  *
  189.  *  high.                                                   *
  190.  *                                                          *
  191.  *  This is skipped for any of the following reasons:       *
  192.  *                                                          *
  193.  *  1.  The side on move is in check.  The null move        *
  194.  *      results in an illegal position.                     *
  195.  *  2.  No more than one null move can appear in succession *
  196.  *      as all this does is burn 6 plies of depth.          *
  197.  *  3.  The side on move has only pawns left, which makes   *
  198.  *      zugzwang positions more likely.                     *
  199.  *  4.  The transposition table probe found an entry that   *
  200.  *      indicates that a null-move search will not fail     *
  201.  *      high, so we avoid the wasted effort.                *
  202.  *                                                          *
  203.  ************************************************************
  204.  */
  205.     tree->inchk[ply + 1] = 0;
  206.     tree->last[ply] = tree->last[ply - 1];
  207.     if (do_null && !pv_node && depth > 1 && !tree->inchk[ply]
  208.         && TotalPieces(side, occupied)) {
  209.       uint64_t save_hash_key;
  210.  
  211.       tree->curmv[ply] = 0;
  212.       tree->phase[ply] = NULL_MOVE;
  213. #if defined(TRACE)
  214.       if (ply <= trace_level)
  215.         Trace(tree, ply, depth, side, beta - 1, beta, "Search1", NULL_MOVE);
  216. #endif
  217.       tree->status[ply + 1] = tree->status[ply];
  218.       Reversible(ply + 1) = 0;
  219.       save_hash_key = HashKey;
  220.       if (EnPassant(ply + 1)) {
  221.         HashEP(EnPassant(ply + 1));
  222.         EnPassant(ply + 1) = 0;
  223.       }
  224.       if (depth - null_depth - 1 > 0)
  225.         value =
  226.             -Search(tree, -beta, -beta + 1, Flip(side),
  227.             depth - null_depth - 1, ply + 1, NO_NULL);
  228.       else
  229.         value = -Quiesce(tree, -beta, -beta + 1, Flip(side), ply + 1, 1);
  230.       HashKey = save_hash_key;
  231.       if (abort_search || tree->stop)
  232.         return 0;
  233.       if (value >= beta) {
  234.         HashStore(tree, ply, depth, side, LOWER, value, tree->hash_move[ply]);
  235.         return value;
  236.       }
  237.     }
  238. /*
  239.  ************************************************************
  240.  *                                                          *
  241.  *  Step 6.  This step is rarely executed.  It is used when *
  242.  *  there is no best move from the hash table, and this is  *
  243.  *  a PV node, since we need a good move to search first.   *
  244.  *  While killers moves are good, they are not quite good   *
  245.  *  enough.  the simplest solution is to try a shallow      *
  246.  *  search (depth-2) to get a move.  note that when we call *
  247.  *  Search() with depth-2, it, too, will not have a hash    *
  248.  *  move, and will therefore recursively continue this      *
  249.  *  process, hence the name "internal iterative deepening." *
  250.  *                                                          *
  251.  ************************************************************
  252.  */
  253.     tree->next_status[ply].phase = HASH_MOVE;
  254.     if (!tree->hash_move[ply] && depth >= 6 && do_null && ply > 1) {
  255.       if (pv_node) {
  256.         do {
  257.           tree->curmv[ply] = 0;
  258.           if (depth - 2 > 0)
  259.             value = Search(tree, alpha, beta, side, depth - 2, ply, DO_NULL);
  260.           else
  261.             value = Quiesce(tree, alpha, beta, side, ply, 1);
  262.           if (abort_search || tree->stop)
  263.             break;
  264.           if (value > alpha) {
  265.             if (value < beta) {
  266.               if ((int) tree->pv[ply - 1].pathl > ply)
  267.                 tree->hash_move[ply] = tree->pv[ply - 1].path[ply];
  268.             } else
  269.               tree->hash_move[ply] = tree->curmv[ply];
  270.             tree->last[ply] = tree->last[ply - 1];
  271.             tree->next_status[ply].phase = HASH_MOVE;
  272.           }
  273.         } while (0);
  274.       }
  275.     }
  276.   }
  277. /*  
  278.  ************************************************************
  279.  *                                                          *
  280.  *  Step 7.  Now iterate through the move list and search   *
  281.  *  the resulting positions.  Note that Search() culls any  *
  282.  *  move that is not legal by using Check().  The special   *
  283.  *  case is that we must find one legal move to search to   *
  284.  *  confirm that it's not a mate or draw.                   *
  285.  *                                                          *
  286.  *  We have three possible procedures we call here, one is  *
  287.  *  specific to ply=1 (NextRootMove()), the second is a     *
  288.  *  specific routine to escape check (NextEvasion()) and    *
  289.  *  the last is the normal NextMove() procedure that does   *
  290.  *  the usual move ordering stuff.                          *
  291.  *                                                          *
  292.  *  Special case:  if we have searched one move at root,    *
  293.  *  and the returned score == alpha, we want to get out of  *
  294.  *  here and return to Iterate() where the search bounds    *
  295.  *  will be adjusted.  Otherwise we would search all root   *
  296.  *  moves and possibly fail low after expending a sig-      *
  297.  *  nificant amount of time.                                *
  298.  *                                                          *
  299.  ************************************************************
  300.  */
  301.   tree->next_status[ply].phase = HASH_MOVE;
  302.   while (1) {
  303.     if (ply > 1)
  304.       tree->phase[ply] =
  305.           (tree->inchk[ply]) ? NextEvasion(tree, ply, side) : NextMove(tree,
  306.           ply, side);
  307.     else if (moves_searched == 1 && alpha == original_alpha)
  308.       break;
  309.     else
  310.       tree->phase[ply] = NextRootMove(tree, tree, side);
  311.     if (!tree->phase[ply])
  312.       break;
  313. #if defined(TRACE)
  314.     if (ply <= trace_level)
  315.       Trace(tree, ply, depth, side, alpha, beta, "Search2", tree->phase[ply]);
  316. #endif
  317.     MakeMove(tree, ply, tree->curmv[ply], side);
  318.     tree->nodes_searched++;
  319.     if (tree->inchk[ply] || !Check(side))
  320.       do {
  321.         if (++moves_searched == 1)
  322.           first_tried = tree->curmv[ply];
  323. /*
  324.  ************************************************************
  325.  *                                                          *
  326.  *  Step 7a.  If the move to be made checks the opponent,   *
  327.  *  then we need to remember that he's in check and also    *
  328.  *  extend the depth by one ply for him to get out.  Note   *
  329.  *  that if the move gives check, it is not a candidate for *
  330.  *  either depth reduction or forward-pruning.              *
  331.  *                                                          *
  332.  *  We do not extend unsafe checking moves (as indicated by *
  333.  *  Swap(), a SEE algorithm, since these are usually a      *
  334.  *  waste of time and simply blow up the tree search space. *
  335.  *                                                          *
  336.  ************************************************************
  337.  */
  338.         extend = 0;
  339.         reduce = 0;
  340.         if (Check(Flip(side))) {
  341.           tree->inchk[ply + 1] = 1;
  342.           if (SwapO(tree, tree->curmv[ply], side) <= 0) {
  343.             extend = check_depth;
  344.             tree->extensions_done++;
  345.           }
  346.         } else
  347.           tree->inchk[ply + 1] = 0;
  348. /*
  349.  ************************************************************
  350.  *                                                          *
  351.  *  Step 7b.  Now for the forward-pruning stuff.  The idea  *
  352.  *  here is based on the old FUTILITY idea, where if the    *
  353.  *  current material + a fudge factor is lower than alpha,  *
  354.  *  then there is little promise in searching this move to  *
  355.  *  make up for the material deficit.  This is not done if  *
  356.  *  we chose to extend this move in the previous step.      *
  357.  *                                                          *
  358.  *  This is a useful idea in today's 20+ ply searches, as   *
  359.  *  when we near the tips, if we are too far behind in      *
  360.  *  material, there is little time left to recover it and   *
  361.  *  moves that don't bring us closer to a reasonable        *
  362.  *  material balance can safely be skipped.  It is much     *
  363.  *  more dangerous in shallow searches.                     *
  364.  *                                                          *
  365.  *  We have an array of pruning margin values that are      *
  366.  *  indexed by depth (remaining plies left until we drop    *
  367.  *  into the quiescence search) and which increase with     *
  368.  *  depth since more depth means a greater chance of        *
  369.  *  bringing the score back up to alpha or beyond.  If the  *
  370.  *  current material + the bonus is less than alpha, we     *
  371.  *  simply avoid searching this move at all, and skip to    *
  372.  *  the next move without expending any more effort.  Note  *
  373.  *  that this is classic forward-pruning and can certainly  *
  374.  *  introduce errors into the search.  However, cluster     *
  375.  *  testing has shown that this improves play in real       *
  376.  *  games.  The current implementation only prunes in the   *
  377.  *  last 5 plies before quiescence, although this can be    *
  378.  *  tuned with the "eval" command changing the "pruning     *
  379.  *  depth" value to something other than 6 (test is for     *
  380.  *  depth < pruning depth, current value is 6 which prunes  *
  381.  *  in last 5 plies only).  Testing shows no benefit in     *
  382.  *  larger values than 6, although this might change in     *
  383.  *  future versions as other things are modified.           *
  384.  *                                                          *
  385.  *  Exception:                                              *
  386.  *                                                          *
  387.  *    We do not prune if we are safely pushing a passed     *
  388.  *    pawn to the 6th rank, where it becomes very dangerous *
  389.  *    since it can promote in two more moves.               *
  390.  *                                                          *
  391.  ************************************************************
  392.  */
  393.         if (tree->phase[ply] == REMAINING_MOVES && !tree->inchk[ply]
  394.             && !extend && moves_searched > 1) {
  395.           if (depth < pruning_depth &&
  396.               MaterialSTM(side) + pruning_margin[depth] <= alpha) {
  397.             if (Piece(tree->curmv[ply]) != pawn ||
  398.                 !Passed(To(tree->curmv[ply]), side)
  399.                 || rankflip[side][Rank(To(tree->curmv[ply]))] < RANK6) {
  400.               tree->moves_fpruned++;
  401.               continue;
  402.             }
  403.           }
  404. /*
  405.  ************************************************************
  406.  *                                                          *
  407.  *  Step 7c.  Now it's time to try to reduce the search     *
  408.  *  depth if the move appears to be "poor".  To reduce the  *
  409.  *  search, the following requirements must be met:         *
  410.  *                                                          *
  411.  *  (1) We must be in the REMAINING_MOVES part of the move  *
  412.  *      ordering, so that we have nearly given up on        *
  413.  *      failing high on any move.                           *
  414.  *                                                          *
  415.  *  (2) We must not be too close to the horizon (this is    *
  416.  *      the LMR_remaining_depth value).                     *
  417.  *                                                          *
  418.  *  (3) The current move must not be a checking move and    *
  419.  *      the side to move can not be in check.               *
  420.  *                                                          *
  421.  ************************************************************
  422.  */
  423.           if (Piece(tree->curmv[ply]) != pawn ||
  424.               !Passed(To(tree->curmv[ply]), side)
  425.               || rankflip[side][Rank(To(tree->curmv[ply]))] < RANK6) {
  426.             reduce = LMR_min_reduction;
  427.             if (moves_searched > 3)
  428.               reduce = LMR_max_reduction;
  429.             max_reduce = Max(depth - 1 - LMR_remaining_depth, 0);
  430.             if (reduce > max_reduce)
  431.               reduce = max_reduce;
  432.             if (reduce)
  433.               tree->reductions_done++;
  434.           }
  435.         }
  436. /*  
  437.  ************************************************************
  438.  *                                                          *
  439.  *  Step 7d.  We have determined whether the depth is to    *
  440.  *  be changed by an extension or a reduction.  If we get   *
  441.  *  to this point, then the move is not being pruned.  So   *
  442.  *  off we go to a recursive search/quiescence call to work *
  443.  *  our way toward a terminal node.                         *
  444.  *                                                          *
  445.  *  There is one special-case to handle.  If the depth was  *
  446.  *  reduced, and Search() returns a value >= beta then      *
  447.  *  accepting that is risky (we reduced the move as we      *
  448.  *  thought it was bad and expected it to fail low) so we   *
  449.  *  repeat the search using the original (non-reduced)      *
  450.  *  depth to see if the fail-high happens again.            *
  451.  *                                                          *
  452.  ************************************************************
  453.  */
  454.         if (depth + extend - reduce - 1 > 0) {
  455.           value =
  456.               -Search(tree, -t_beta, -alpha, Flip(side),
  457.               depth + extend - reduce - 1, ply + 1, DO_NULL);
  458.           if (value > alpha && reduce)
  459.             value =
  460.                 -Search(tree, -t_beta, -alpha, Flip(side), depth - 1, ply + 1,
  461.                 DO_NULL);
  462.         } else
  463.           value = -Quiesce(tree, -t_beta, -alpha, Flip(side), ply + 1, 1);
  464.         if (abort_search || tree->stop)
  465.           break;
  466. /*
  467.  ************************************************************
  468.  *                                                          *
  469.  *  Step 7e.  This is the PVS re-search code.  If we reach  *
  470.  *  this point and value > alpha and value < beta, then     *
  471.  *  this can not be a null-window search.  We have to re-   *
  472.  *  search the position with the original beta value (not   *
  473.  *  alpha+1 as is the usual case in PVS) to see if it still *
  474.  *  fails high before we treat this as a real fail-high and *
  475.  *  back up the value to the previous ply.                  *
  476.  *                                                          *
  477.  *  Special case:  ply == 1.                                *
  478.  *                                                          *
  479.  *  In this case, we need to clean up and then move the     *
  480.  *  best move to the top of the root move list, and return  *
  481.  *  back to Iterate() to let it produce the usual informa-  *
  482.  *  tive output and re-start the search with a new beta     *
  483.  *  value.  We also reset the failhi_delta back to 16,      *
  484.  *  since an earlier fail-high or fail low in this          *
  485.  *  iteration could have left it at a large value.          *
  486.  *                                                          *
  487.  *  Last step is to build a usable PV in case this move     *
  488.  *  fails low on the re-search, because we do want to play  *
  489.  *  this move no matter what happens.                       *
  490.  *                                                          *
  491.  ************************************************************
  492.  */
  493.         if (value > alpha && value < beta && moves_searched > 1) {
  494.           if (ply == 1) {
  495.             alpha = value;
  496.             UnmakeMove(tree, ply, tree->curmv[ply], side);
  497.             root_beta = alpha;
  498.             failhi_delta = 16;
  499.             for (i = 0; i < n_root_moves; i++)
  500.               if (tree->curmv[1] == root_moves[i].move)
  501.                 break;
  502.             if (i < n_root_moves) {
  503.               temp_rm = root_moves[i];
  504.               for (; i > 0; i--)
  505.                 root_moves[i] = root_moves[i - 1];
  506.               root_moves[0] = temp_rm;
  507.             }
  508.             root_moves[0].bm_age = 4;
  509.             tree->pv[1].path[1] = tree->curmv[1];
  510.             tree->pv[1].pathl = 2;
  511.             tree->pv[1].pathh = 0;
  512.             tree->pv[1].pathd = iteration_depth;
  513.             tree->pv[0] = tree->pv[1];
  514.             return alpha;
  515.           }
  516.           if (depth + extend - 1 > 0)
  517.             value =
  518.                 -Search(tree, -beta, -alpha, Flip(side), depth + extend - 1,
  519.                 ply + 1, DO_NULL);
  520.           else
  521.             value = -Quiesce(tree, -beta, -alpha, Flip(side), ply + 1, 1);
  522.           if (abort_search || tree->stop)
  523.             break;
  524.         }
  525. /*  
  526.  ************************************************************
  527.  *                                                          *
  528.  *  Step 7f.  We have completed the search/re-search and we *
  529.  *  we have the final score.  Now we need to check for a    *
  530.  *  fail-high which terminates this search instantly since  *
  531.  *  no further searching is required.  On a fail high, we   *
  532.  *  need to update the killer moves, and hash table before  *
  533.  *  we return.                                              *
  534.  *                                                          *
  535.  *  If ply == 1, we call Output() which will dump the new   *
  536.  *  PV.  But but we need to back up the PV to ply=0 so that *
  537.  *  it will be available to tell main() which move to make. *
  538.  *                                                          *
  539.  ************************************************************
  540.  */
  541.         if (value > alpha) {
  542.           alpha = value;
  543.           if (ply == 1) {
  544.             tree->pv[1].pathv = value;
  545.             Output(tree, beta);
  546.             tree->pv[0] = tree->pv[1];
  547.           }
  548.           if (value >= beta) {
  549.             Killer(tree, ply, tree->curmv[ply]);
  550.             UnmakeMove(tree, ply, tree->curmv[ply], side);
  551.             HashStore(tree, ply, depth, side, LOWER, value, tree->curmv[ply]);
  552.             tree->fail_highs++;
  553.             if (moves_searched == 1)
  554.               tree->fail_high_first_move++;
  555.             return value;
  556.           }
  557.         }
  558.         t_beta = alpha + 1;
  559.       } while (0);
  560.     UnmakeMove(tree, ply, tree->curmv[ply], side);
  561.     if (abort_search || tree->stop)
  562.       return 0;
  563. /*
  564.  ************************************************************
  565.  *                                                          *
  566.  *  Step 7g.  If are doing an SMP search, and we have idle  *
  567.  *  processors, now is the time to get them involved.  We   *
  568.  *  have now satisfied the "young brothers wait" condition  *
  569.  *  since we have searched one move.  All that is left is   *
  570.  *  to check the split constraints to see if we are an      *
  571.  *  acceptable split point.                                 *
  572.  *                                                          *
  573.  *    (1) We can't split within N plies of the frontier     *
  574.  *        nodes to avoid excessive split overhead.          *
  575.  *                                                          *
  576.  *    (2) We can't split until at least M nodes have been   *
  577.  *        searched since this thread was last split, to     *
  578.  *        avoid splitting too often, mainly in endgames.    *
  579.  *                                                          *
  580.  *    (3) We have to have searched one legal move to avoid  *
  581.  *        splitting at a node where we have no legal moves  *
  582.  *        (the first move tried might have been illegal as  *
  583.  *        in when we encounter a stalemate).                *
  584.  *                                                          *
  585.  *    (4) If we are at ply=1, we can't split unless the     *
  586.  *        smp_split_at_root flag is set to 1, AND the next  *
  587.  *        move in the ply=1 move list is not flagged as     *
  588.  *        "do not search in parallel" which happens when    *
  589.  *        this move was a best move in the last couple of   *
  590.  *        searches and we want all processors on it at once *
  591.  *        to get a score back quicker.                      *
  592.  *                                                          *
  593.  *    (5) if the variable smp_split is > 0, we have idle    *
  594.  *        threads that can help, however if smp_split < 0,  *
  595.  *        we are already doing a split on another thread    *
  596.  *        so there is no point in waiting to try one here.  *
  597.  *                                                          *
  598.  *  SearchParallel() primarily contains steps 7 through 7f  *
  599.  *  which is the main search loop.  We do the final clean-  *
  600.  *  up below when either we finish the search normally or   *
  601.  *  a parallel search completes and returns to this point.  *
  602.  *                                                          *
  603.  *  Special case:  we do not split if we are at ply=1 and   *
  604.  *  alpha == original_alpha.  That means the first move     *
  605.  *  failed low, and we are going to exit search and return  *
  606.  *  to Iterate() to report this.                            *
  607.  *                                                          *
  608.  *  One potential problem is that multiple threads can get  *
  609.  *  to this point at the same time, and they all stack up   *
  610.  *  waiting to grab the lock_smp lock that protects the     *
  611.  *  split operation.  I now have a new lock, lock_split,    *
  612.  *  to try to limit this wasted time.  A thread now has to  *
  613.  *  acquire that lock, and then it tests the smp_split      *
  614.  *  to see if a split STILL needs to be done.  If not, we   *
  615.  *  release the lock and move on, rather than waiting on    *
  616.  *  main lock_smp lock.                                     *
  617.  *                                                          *
  618.  *  If we acquire the lock_split lock AND we notice that    *
  619.  *  smp_split is still set to 1, we quickly set smp_split   *
  620.  *  to zero (-1) so that other threads will bug out rather  *
  621.  *  than trying to split and end up in a queue behind us,   *
  622.  *  waiting while we split and they try to split and fail.  *
  623.  *  We release lock_split to eliminate the log-jam of       *
  624.  *  threads waiting to split and get them back into their   *
  625.  *  normal searches, and jump right into Thread().          *
  626.  *                                                          *
  627.  *  The smp_split = -1 has a complex meaning, but simply    *
  628.  *  stated it means "split currently in progress".  Here,   *
  629.  *  that means "do not attempt a split since we are already *
  630.  *  in the middle of one."  It also tells individual        *
  631.  *  threads to not change smp_split to 1 when they become   *
  632.  *  idle, because with a split in progress, it is likely we *
  633.  *  will pick them up automatically.                        *
  634.  *                                                          *
  635.  ************************************************************
  636.  */
  637. #if (CPUS > 1)
  638.     if (smp_split > 0 && depth >= smp_min_split_depth && moves_searched &&
  639.         tree->nodes_searched - start_nodes > smp_split_nodes && (ply > 1 ||
  640.             (smp_split_at_root && NextRootMoveParallel() &&
  641.                 alpha != original_alpha)))
  642.       do {
  643.         Lock(lock_split);
  644.         if (smp_split <= 0) {
  645.           Unlock(lock_split);
  646.           break;
  647.         }
  648.         smp_split = -1;
  649.         Unlock(lock_split);
  650.         tree->alpha = alpha;
  651.         tree->beta = beta;
  652.         tree->value = alpha;
  653.         tree->side = side;
  654.         tree->ply = ply;
  655.         tree->depth = depth;
  656.         tree->moves_searched = moves_searched;
  657.         if (Thread(tree)) {
  658.           if (abort_search || tree->stop)
  659.             return 0;
  660.           if (tree->thread_id == 0 && CheckInput())
  661.             Interrupt(ply);
  662.           value = tree->value;
  663.           if (value > alpha) {
  664.             if (value >= beta) {
  665.               HashStore(tree, ply, depth, side, LOWER, value, tree->cutmove);
  666.               return value;
  667.             }
  668.             alpha = value;
  669.             break;
  670.           }
  671.         }
  672.       } while (0);
  673. #endif
  674.   }
  675. /*
  676.  ************************************************************
  677.  *                                                          *
  678.  *  Step 8.  All moves have been searched.  If none were    *
  679.  *  legal, return either MATE or DRAW depending on whether  *
  680.  *  the side to move is in check or not.                    *
  681.  *                                                          *
  682.  ************************************************************
  683.  */
  684.   if (abort_search || tree->stop)
  685.     return 0;
  686.   if (moves_searched == 0) {
  687.     value = (Check(side)) ? -(MATE - ply) : DrawScore(side);
  688.     if (value >= alpha && value < beta) {
  689.       SavePV(tree, ply, 0);
  690. #if defined(TRACE)
  691.       if (ply <= trace_level)
  692.         printf("Search() no moves!  ply=%d\n", ply);
  693. #endif
  694.     }
  695.     return value;
  696.   } else {
  697.     int bestmove, type;
  698.     bestmove =
  699.         (alpha == original_alpha) ? first_tried : tree->pv[ply].path[ply];
  700.     type = (alpha == original_alpha) ? UPPER : EXACT;
  701.     if (repeat == 2 && alpha != -(MATE - ply - 1)) {
  702.       value = DrawScore(side);
  703.       if (value < beta)
  704.         SavePV(tree, ply, 0);
  705. #if defined(TRACE)
  706.       if (ply <= trace_level)
  707.         printf("draw by 50 move rule detected, ply=%d.\n", ply);
  708. #endif
  709.       return value;
  710.     } else if (alpha != original_alpha) {
  711.       tree->pv[ply - 1] = tree->pv[ply];
  712.       tree->pv[ply - 1].path[ply - 1] = tree->curmv[ply - 1];
  713.       Killer(tree, ply, tree->pv[ply].path[ply]);
  714.     }
  715.     HashStore(tree, ply, depth, side, type, alpha, bestmove);
  716.     return alpha;
  717.   }
  718. }
  719.  
  720. /* last modified 05/08/14 */
  721. /*
  722.  *******************************************************************************
  723.  *                                                                             *
  724.  *   SearchParallel() is the recursive routine used to implement alpha/beta    *
  725.  *   negamax search using parallel threads.  When this code is called, the     *
  726.  *   first move has already been searched, so all that is left is to search    *
  727.  *   the remainder of the moves and then return.  Note that the hash table and *
  728.  *   such can't be modified here since this only represents a part of the      *
  729.  *   search at this ply.  All of that is deferred until we return and reach    *
  730.  *   the original instance of Search() where we have the complete results from *
  731.  *   all the threads that are helping here.                                    *
  732.  *                                                                             *
  733.  *******************************************************************************
  734.  */
  735. int SearchParallel(TREE * RESTRICT tree, int alpha, int beta, int value,
  736.     int side, int depth, int ply) {
  737.   ROOT_MOVE temp_rm;
  738.   int extend, reduce, max_reduce, i;
  739.  
  740. /*
  741.  ************************************************************
  742.  *                                                          *
  743.  *  Step 7.  Now we continue to iterate through the move    *
  744.  *  list and search the resulting positions.  Note that     *
  745.  *  SearchParallel() culls any move that is not legal by    *
  746.  *  using Check().  The special case mentioned in Search()  *
  747.  *  is not an issue here as we don't do a parallel split    *
  748.  *  until we have searched one legal move.                  *
  749.  *                                                          *
  750.  *  We have three possible procedures we call here, one is  *
  751.  *  specific to ply=1 (NextRootMove()), the second is a     *
  752.  *  specific routine to escape check (NextEvasion()) and    *
  753.  *  the last is the normal NextMove() procedure that does   *
  754.  *  the usual move ordering stuff.                          *
  755.  *                                                          *
  756.  ************************************************************
  757.  */
  758.  
  759.   while (1) {
  760.     Lock(tree->parent->lock);
  761.     if (ply > 1)
  762.       tree->phase[ply] =
  763.           (tree->inchk[ply]) ? NextEvasion((TREE *) tree->parent, ply,
  764.           side) : NextMove((TREE *)
  765.           tree->parent, ply, side);
  766.     else
  767.       tree->phase[ply] = NextRootMove(tree->parent, tree, side);
  768.     tree->curmv[ply] = tree->parent->curmv[ply];
  769.     Unlock(tree->parent->lock);
  770.     if (!tree->phase[ply])
  771.       break;
  772. #if defined(TRACE)
  773.     if (ply <= trace_level)
  774.       Trace(tree, ply, depth, side, alpha, beta, "SearchParallel",
  775.           tree->phase[ply]);
  776. #endif
  777.     MakeMove(tree, ply, tree->curmv[ply], side);
  778.     tree->nodes_searched++;
  779.     if (tree->inchk[ply] || !Check(side))
  780.       do {
  781.         tree->parent->moves_searched++;
  782. /*
  783.  ************************************************************
  784.  *                                                          *
  785.  *  Step 7a.  If the move to be made checks the opponent,   *
  786.  *  then we need to remember that he's in check and also    *
  787.  *  extend the depth by one ply for him to get out.  Note   *
  788.  *  that if the move gives check, it is not a candidate for *
  789.  *  either depth reduction or forward-pruning.              *
  790.  *                                                          *
  791.  *  We do not extend unsafe checking moves (as indicated by *
  792.  *  Swap(), a SEE algorithm, since these are usually a      *
  793.  *  waste of time and simply blow up the tree search space. *
  794.  *                                                          *
  795.  ************************************************************
  796.  */
  797.         extend = 0;
  798.         reduce = 0;
  799.         if (Check(Flip(side))) {
  800.           tree->inchk[ply + 1] = 1;
  801.           if (SwapO(tree, tree->curmv[ply], side) <= 0) {
  802.             extend = check_depth;
  803.             tree->extensions_done++;
  804.           }
  805.         } else
  806.           tree->inchk[ply + 1] = 0;
  807. /*
  808.  ************************************************************
  809.  *                                                          *
  810.  *  Step 7b.  Now for the forward-pruning stuff.  The idea  *
  811.  *  here is based on the old FUTILITY idea, where if the    *
  812.  *  current material + a fudge factor is lower than alpha,  *
  813.  *  then there is little promise in searching this move to  *
  814.  *  make up for the material deficit.  This is not done if  *
  815.  *  we chose to extend this move in the previous step.      *
  816.  *                                                          *
  817.  *  This is a useful idea in today's 20+ ply searches, as   *
  818.  *  when we near the tips, if we are too far behind in      *
  819.  *  material, there is little time left to recover it and   *
  820.  *  moves that don't bring us closer to a reasonable        *
  821.  *  material balance can safely be skipped.  It is much     *
  822.  *  more dangerous in shallow searches.                     *
  823.  *                                                          *
  824.  *  We have an array of pruning margin values that are      *
  825.  *  indexed by depth (remaining plies left until we drop    *
  826.  *  into the quiescence search) and which increase with     *
  827.  *  depth since more depth means a greater chance of        *
  828.  *  bringing the score back up to alpha or beyond.  If the  *
  829.  *  current material + the bonus is less than alpha, we     *
  830.  *  simply avoid searching this move at all, and skip to    *
  831.  *  the next move without expending any more effort.  Note  *
  832.  *  that this is classic forward-pruning and can certainly  *
  833.  *  introduce errors into the search.  However, cluster     *
  834.  *  testing has shown that this improves play in real       *
  835.  *  games.  The current implementation only prunes in the   *
  836.  *  last 5 plies before quiescence, although this can be    *
  837.  *  tuned with the "eval" command changing the "pruning     *
  838.  *  depth" value to something other than 6 (test is for     *
  839.  *  depth < pruning depth, current value is 6 which prunes  *
  840.  *  in last 5 plies only).  Testing shows no benefit in     *
  841.  *  larger values than 6, although this might change in     *
  842.  *  future versions as other things are modified.           *
  843.  *                                                          *
  844.  *  Exception:                                              *
  845.  *                                                          *
  846.  *    We do not prune if we are safely pushing a passed     *
  847.  *    pawn to the 6th rank, where it becomes very dangerous *
  848.  *    since it can promote in two more moves.               *
  849.  *                                                          *
  850.  ************************************************************
  851.  */
  852.         if (tree->phase[ply] == REMAINING_MOVES && !tree->inchk[ply]
  853.             && !extend && tree->parent->moves_searched > 1) {
  854.           if (depth < pruning_depth &&
  855.               MaterialSTM(side) + pruning_margin[depth] <= alpha) {
  856.             if (Piece(tree->curmv[ply]) != pawn ||
  857.                 !Passed(To(tree->curmv[ply]), side)
  858.                 || rankflip[side][Rank(To(tree->curmv[ply]))] < RANK6) {
  859.               tree->moves_fpruned++;
  860.               continue;
  861.             }
  862.           }
  863. /*
  864.  ************************************************************
  865.  *                                                          *
  866.  *  Step 7c.  Now it's time to try to reduce the search     *
  867.  *  depth if the move appears to be "poor".  To reduce the  *
  868.  *  search, the following requirements must be met:         *
  869.  *                                                          *
  870.  *  (1) We must be in the REMAINING_MOVES part of the move  *
  871.  *      ordering, so that we have nearly given up on        *
  872.  *      failing high on any move.                           *
  873.  *                                                          *
  874.  *  (2) We must not be too close to the horizon (this is    *
  875.  *      the LMR_remaining_depth value).                     *
  876.  *                                                          *
  877.  *  (3) The current move must not be a checking move and    *
  878.  *      the side to move can not be in check.               *
  879.  *                                                          *
  880.  ************************************************************
  881.  */
  882.           if (Piece(tree->curmv[ply]) != pawn ||
  883.               !Passed(To(tree->curmv[ply]), side)
  884.               || rankflip[side][Rank(To(tree->curmv[ply]))] < RANK6) {
  885.             reduce = LMR_min_reduction;
  886.             if (tree->parent->moves_searched > 3)
  887.               reduce = LMR_max_reduction;
  888.             max_reduce = Max(depth - 1 - LMR_remaining_depth, 0);
  889.             if (reduce > max_reduce)
  890.               reduce = max_reduce;
  891.             if (reduce)
  892.               tree->reductions_done++;
  893.           }
  894.         }
  895. /*
  896.  ************************************************************
  897.  *                                                          *
  898.  *  Step 7d.  We have determined whether the depth is to    *
  899.  *  be changed by an extension or a reduction.  If we get   *
  900.  *  to this point, then the move is not being pruned.  So   *
  901.  *  off we go to a recursive search/quiescence call to work *
  902.  *  our way toward a terminal node.                         *
  903.  *                                                          *
  904.  *  There is one special-cases to handle.  If the depth was *
  905.  *  reduced, and Search() returns a value >= beta then      *
  906.  *  accepting that is risky (we reduced the move as we      *
  907.  *  thought it was bad and expected it to fail low) so we   *
  908.  *  repeat the search using the original (non-reduced)      *
  909.  *  depth to see if the fail-high happens again.            *
  910.  *                                                          *
  911.  ************************************************************
  912.  */
  913.         if (depth + extend - reduce - 1 > 0) {
  914.           value =
  915.               -Search(tree, -alpha - 1, -alpha, Flip(side),
  916.               depth + extend - reduce - 1, ply + 1, DO_NULL);
  917.           if (value > alpha && reduce)
  918.             value =
  919.                 -Search(tree, -alpha - 1, -alpha, Flip(side), depth - 1,
  920.                 ply + 1, DO_NULL);
  921.         } else
  922.           value = -Quiesce(tree, -alpha - 1, -alpha, Flip(side), ply + 1, 1);
  923.         if (abort_search || tree->stop)
  924.           break;
  925. /*
  926.  ************************************************************
  927.  *                                                          *
  928.  *  Step 7e.  This is the PVS re-search code.  If we reach  *
  929.  *  this point and value > alpha and value < beta, then     *
  930.  *  this can not be a null-window search.  We have to re-   *
  931.  *  search the position with the original beta value (not   *
  932.  *  alpha+1 as is the usual case in PVS) to see if it still *
  933.  *  fails high before we treat this as a real fail-high and *
  934.  *  back up the value to the previous ply.                  *
  935.  *                                                          *
  936.  *  Special case:  ply == 1.                                *
  937.  *                                                          *
  938.  *  In this case, we need to clean up and then move the     *
  939.  *  best move to the top of the root move list, and then    *
  940.  *  return back to the normal Search(), which will then     *
  941.  *  return back to Iterate() to let it produce the usual    *
  942.  *  informative output and re-start the search with a new   *
  943.  *  beta value.  We also reset the failhi_delta back to 16, *
  944.  *  since an earlier fail-high or fail low in this          *
  945.  *  iteration could have left it at a large value.          *
  946.  *                                                          *
  947.  *  Last step is to build a usable PV in case this move     *
  948.  *  fails low on the re-search, because we do want to play  *
  949.  *  this move no matter what happens.                       *
  950.  *                                                          *
  951.  ************************************************************
  952.  */
  953.         if (value > alpha && value < beta) {
  954.           if (ply == 1) {
  955.             int proc;
  956.  
  957.             alpha = value;
  958.             parallel_aborts++;
  959.             UnmakeMove(tree, ply, tree->curmv[ply], side);
  960.             Lock(lock_smp);
  961.             Lock(tree->parent->lock);
  962.             if (!tree->stop) {
  963.               for (proc = 0; proc < smp_max_threads; proc++)
  964.                 if (tree->parent->siblings[proc] && proc != tree->thread_id)
  965.                   ThreadStop(tree->parent->siblings[proc]);
  966.               root_beta = alpha;
  967.               failhi_delta = 16;
  968.               Lock(lock_root);
  969.               for (i = 0; i < n_root_moves; i++)
  970.                 if (tree->curmv[1] == root_moves[i].move)
  971.                   break;
  972.               if (i < n_root_moves) {
  973.                 temp_rm = root_moves[i];
  974.                 for (; i > 0; i--)
  975.                   root_moves[i] = root_moves[i - 1];
  976.                 root_moves[0] = temp_rm;
  977.               }
  978.               root_moves[0].bm_age = 4;
  979.               Unlock(lock_root);
  980.               tree->pv[1].path[1] = tree->curmv[1];
  981.               tree->pv[1].pathl = 2;
  982.               tree->pv[1].pathh = 0;
  983.               tree->pv[1].pathd = iteration_depth;
  984.               tree->pv[0] = tree->pv[1];
  985.             }
  986.             Unlock(tree->parent->lock);
  987.             Unlock(lock_smp);
  988.             return alpha;
  989.           }
  990.           if (depth + extend - 1 > 0)
  991.             value =
  992.                 -Search(tree, -beta, -alpha, Flip(side), depth + extend - 1,
  993.                 ply + 1, DO_NULL);
  994.           else
  995.             value = -Quiesce(tree, -beta, -alpha, Flip(side), ply + 1, 1);
  996.           if (abort_search || tree->stop)
  997.             break;
  998.         }
  999. /*
  1000.  ************************************************************
  1001.  *                                                          *
  1002.  *  Step 7f.  We have completed the search/re-search and we *
  1003.  *  we have the final score.  Now we need to check for a    *
  1004.  *  fail-high which terminates this search instantly since  *
  1005.  *  no further searching is required.  On a fail high, we   *
  1006.  *  need to update the killer moves, and hash table before  *
  1007.  *  we return.                                              *
  1008.  *                                                          *
  1009.  *  Note that we can not produce a new PV here.  At best,   *
  1010.  *  we can produce a fail-high which will abort other       *
  1011.  *  threads at this node (wasting time).                    *
  1012.  *                                                          *
  1013.  *  Special case:  If ply == 1, and we fail high on the     *
  1014.  *  null-window search, we simply abort the search and then *
  1015.  *  return to the normal search, which will back us out to  *
  1016.  *  Iterate() and inform the user and re-start the search.  *
  1017.  *                                                          *
  1018.  *  We then stop all threads (except the current thread     *
  1019.  *  that is dealing with the fail high) since we are going  *
  1020.  *  to back out quickly and then start a new search from    *
  1021.  *  the root position.  The split-block sibling ids lets us *
  1022.  *  know which threads should be stopped, and since we are  *
  1023.  *  at the root (ply == 1) that essentially means "all      *
  1024.  *  threads except for this one."                           *
  1025.  *                                                          *
  1026.  ************************************************************
  1027.  */
  1028.         if (value > alpha) {
  1029.           alpha = value;
  1030.           if (value >= beta) {
  1031.             int proc;
  1032.  
  1033.             parallel_aborts++;
  1034.             UnmakeMove(tree, ply, tree->curmv[ply], side);
  1035.             Lock(lock_smp);
  1036.             Lock(tree->parent->lock);
  1037.             if (!tree->stop)
  1038.               for (proc = 0; proc < smp_max_threads; proc++)
  1039.                 if (tree->parent->siblings[proc] && proc != tree->thread_id)
  1040.                   ThreadStop(tree->parent->siblings[proc]);
  1041.             Unlock(tree->parent->lock);
  1042.             Unlock(lock_smp);
  1043.             return alpha;
  1044.           }
  1045.         }
  1046.       } while (0);
  1047.     UnmakeMove(tree, ply, tree->curmv[ply], side);
  1048.     if (abort_search || tree->stop)
  1049.       break;
  1050.   }
  1051. /*
  1052.  ************************************************************
  1053.  *                                                          *
  1054.  *  Step 8.  We are doing an SMP search, so there are no    *
  1055.  *  "end-of-search" things to do.  We have searched all the *
  1056.  *  remaining moves at this ply in parallel, and now return *
  1057.  *  and let the original search that started this sub-tree) *
  1058.  *  clean up, and do the tests for mate/stalemate, update   *
  1059.  *  the hash table, etc.                                    *
  1060.  *                                                          *
  1061.  *  As we return, we end back up in Thread() where we       *
  1062.  *  started, which then copies the best score/etc back to   *
  1063.  *  the parent thread.                                      *
  1064.  *                                                          *
  1065.  *  We do need to flag the root move we tried to search, if *
  1066.  *  we were stopped early due to another root move failing  *
  1067.  *  high.  Otherwise this move appears to have been         *
  1068.  *  searched already and will not be searched again until   *
  1069.  *  the next iteration.                                     *
  1070.  *                                                          *
  1071.  ************************************************************
  1072.  */
  1073.   if (tree->stop && ply == 1) {
  1074.     int which;
  1075.  
  1076.     Lock(lock_root);
  1077.     for (which = 0; which < n_root_moves; which++)
  1078.       if (root_moves[which].move == tree->curmv[ply]) {
  1079.         root_moves[which].status &= 0xf7;
  1080.         break;
  1081.       }
  1082.     Unlock(lock_root);
  1083.   }
  1084.   return alpha;
  1085. }
  1086.