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. #include "epdglue.h"
  4. /* last modified 04/24/14 */
  5. /*
  6.  *******************************************************************************
  7.  *                                                                             *
  8.  *   Iterate() is the routine used to drive the iterated search.  It           *
  9.  *   repeatedly calls search, incrementing the search depth after each call,   *
  10.  *   until either time is exhausted or the maximum set search depth is         *
  11.  *   reached.                                                                  *
  12.  *                                                                             *
  13.  *   Crafty has several specialized modes that influence how moves are chosen  *
  14.  *   and when.                                                                 *
  15.  *                                                                             *
  16.  *   (1) "mode tournament" is a special way of handling book moves.  Here we   *
  17.  *   are dealing with pondering.  We play our move, and then we take all of    *
  18.  *   the known book moves for the opponent (moves where we have an instant     *
  19.  *   reply since they are in the book) and eliminate those from the set of     *
  20.  *   root moves to search.  We do a short search to figure out which of those  *
  21.  *   non-book moves is best, and then we ponder that move.  It will look like  *
  22.  *   we are always out of book, but we are not.  We are just looking for one   *
  23.  *   of two cases:  (i) The opponent's book runs out and he doesn't play the   *
  24.  *   expected book line (which is normally a mistake), where this will give us *
  25.  *   a good chance of pondering the move he will actually play (a non-book     *
  26.  *   move) without sitting around and doing nothing until he takes us out of   *
  27.  *   book;  (ii) Our book doesn't have a reasonable choice, so we do a search  *
  28.  *   and ponder a better choice so again we are not wasting time.  The value   *
  29.  *   of "mode" will be set to "tournament" to enable this.                     *
  30.  *                                                                             *
  31.  *   (2) "book random 0" tells the program to enumerate the list of known book *
  32.  *   moves, but rather than playing one randomly, we do a shortened search and *
  33.  *   use the normal move selection approach (which will, unfortunately, accept *
  34.  *   many gambits that a normal book line would bypass as too risky.  But this *
  35.  *   can also find a better book move in many positions, since many book lines *
  36.  *   are not verified with computer searches.                                  *
  37.  *                                                                             *
  38.  *   Those modes are handled within Book() and Ponder() but they all use the   *
  39.  *   same iterated search as is used for normal moves.                         *
  40.  *                                                                             *
  41.  *******************************************************************************
  42.  */
  43. int Iterate(int wtm, int search_type, int root_list_done) {
  44.   TREE *const tree = block[0];
  45.   int i, root_alpha, old_root_alpha, old_root_beta;
  46.   int value = 0, twtm, correct, correct_count;
  47.   char *fl_indicator, *fh_indicator;
  48. #if (CPUS > 1)
  49. #ifdef UNIX // Pierre-Marie Baty -- this variable is only used on UNIX
  50.   pthread_t pt;
  51. #endif // UNIX
  52. #endif
  53.  
  54. /*
  55.  ************************************************************
  56.  *                                                          *
  57.  *  Initialize draw score.  This has to be done here since  *
  58.  *  we don't know whether we are searching for black or     *
  59.  *  white until we get to this point.                       *
  60.  *                                                          *
  61.  ************************************************************
  62.  */
  63.   if (wtm) {
  64.     draw_score[0] = -abs_draw_score;
  65.     draw_score[1] = abs_draw_score;
  66.   } else {
  67.     draw_score[0] = abs_draw_score;
  68.     draw_score[1] = -abs_draw_score;
  69.   }
  70. #if defined(NODES)
  71.   temp_search_nodes = search_nodes;
  72. #endif
  73. /*
  74.  ************************************************************
  75.  *                                                          *
  76.  *  Initialize statistical counters and such.               *
  77.  *                                                          *
  78.  ************************************************************
  79.  */
  80.   idle_time = 0;
  81.   tree->curmv[0] = 0;
  82.   abort_search = 0;
  83.   book_move = 0;
  84.   program_start_time = ReadClock();
  85.   start_time = ReadClock();
  86.   root_wtm = wtm;
  87.   kibitz_depth = 0;
  88.   tree->nodes_searched = 0;
  89.   tree->fail_highs = 0;
  90.   tree->fail_high_first_move = 0;
  91.   parallel_splits = 0;
  92.   parallel_aborts = 0;
  93.   correct_count = 0;
  94.   burp = 15 * 100;
  95.   transposition_age = (transposition_age + 1) & 0x1ff;
  96.   next_time_check = nodes_between_time_checks;
  97.   tree->evaluations = 0;
  98.   tree->egtb_probes = 0;
  99.   tree->egtb_probes_successful = 0;
  100.   tree->extensions_done = 0;
  101.   tree->qchecks_done = 0;
  102.   tree->reductions_done = 0;
  103.   tree->moves_fpruned = 0;
  104.   root_wtm = wtm;
  105. /*
  106.  ************************************************************
  107.  *                                                          *
  108.  *  We do a quick check to see if this position has a known *
  109.  *  book reply.  If not, we drop into the main iterated     *
  110.  *  search, otherwise we skip to the bottom and return the  *
  111.  *  move that Book() returned.                              *
  112.  *                                                          *
  113.  *  Note the "booking" exception below.  If you use the     *
  114.  *  "book random 0" you instruct Crafty to enumerate the    *
  115.  *  known set of book moves, and then initiate a normal     *
  116.  *  iterated search, but with just those known book moves   *
  117.  *  included in the root move list.  We therefore choose    *
  118.  *  (based on a normal search / evaluation but with a lower *
  119.  *  time limit) from the book moves given.                  *
  120.  *                                                          *
  121.  ************************************************************
  122.  */
  123.   if (booking || !Book(tree, wtm, root_list_done))
  124.     do {
  125.       if (abort_search)
  126.         break;
  127. #if !defined(NOEGTB)
  128.       if (EGTB_draw && !puzzling && swindle_mode)
  129.         EGTB_use = 0;
  130.       else
  131.         EGTB_use = EGTBlimit;
  132.       if (EGTBlimit && !EGTB_use)
  133.         Print(128, "Drawn at root, trying for swindle.\n");
  134. #endif
  135. /*
  136.  ************************************************************
  137.  *                                                          *
  138.  *  The first action for a real search is to generate the   *
  139.  *  root move list if it has not already been done.  For    *
  140.  *  some circumstances, such as a non-random book move      *
  141.  *  search, we are given the root move list, which only     *
  142.  *  contains the known book moves.  Those are all we need   *
  143.  *  to search.  If there are no legal moves, it is either   *
  144.  *  mate or draw depending on whether the side to move is   *
  145.  *  in check or not (mate or stalemate.)                    *
  146.  *                                                          *
  147.  *  Why would there be already be a root move list?  See    *
  148.  *  the two modes described at the top (mode tournament and *
  149.  *  book random 0) which would have already inserted just   *
  150.  *  the moves that should be searched.                      *
  151.  *                                                          *
  152.  ************************************************************
  153.  */
  154.       if (!root_list_done)
  155.         RootMoveList(wtm);
  156.       if (n_root_moves == 0) {
  157.         program_end_time = ReadClock();
  158.         tree->pv[0].pathl = 0;
  159.         tree->pv[0].pathd = 0;
  160.         if (Check(wtm))
  161.           value = -(MATE - 1);
  162.         else
  163.           value = DrawScore(wtm);
  164.         Print(6, "        depth     time       score   variation\n");
  165.         Print(6, "                                     (no moves)\n");
  166.         tree->nodes_searched = 1;
  167.         if (!puzzling)
  168.           last_root_value = value;
  169.         return value;
  170.       }
  171. /*
  172.  ************************************************************
  173.  *                                                          *
  174.  *  Now set the search time and iteratively call Search()   *
  175.  *  to analyze the position deeper and deeper.  Note that   *
  176.  *  Search() is called with an alpha/beta window roughly    *
  177.  *  1/3 of a pawn wide, centered on the score last returned *
  178.  *  by search.                                              *
  179.  *                                                          *
  180.  ************************************************************
  181.  */
  182.       TimeSet(search_type);
  183.       iteration_depth = 1;
  184.       noise_block = 0;
  185.       if (last_pv.pathd > 1) {
  186.         iteration_depth = last_pv.pathd + 1;
  187.         value = last_root_value;
  188.         tree->pv[0] = last_pv;
  189.         noise_block = 1;
  190.       } else
  191.         difficulty = 100;
  192.       Print(6, "        depth     time       score   variation (%d)\n",
  193.           iteration_depth);
  194.       abort_search = 0;
  195. /*
  196.  ************************************************************
  197.  *                                                          *
  198.  *  Set the initial search bounds based on the last search  *
  199.  *  or default values.                                      *
  200.  *                                                          *
  201.  ************************************************************
  202.  */
  203.       tree->pv[0] = last_pv;
  204.       if (iteration_depth > 1) {
  205.         root_alpha = Max(-MATE, last_value - 16);
  206.         root_beta = Min(MATE, last_value + 16);
  207.       } else {
  208.         root_alpha = -MATE;
  209.         root_beta = MATE;
  210.       }
  211. /*
  212.  ************************************************************
  213.  *                                                          *
  214.  *  If we are using multiple threads, and they have not     *
  215.  *  been started yet, then start them now as the search is  *
  216.  *  ready to begin.                                         *
  217.  *                                                          *
  218.  ************************************************************
  219.  */
  220. #if (CPUS > 1)
  221.       if (smp_max_threads > smp_idle + 1) {
  222.         long proc;
  223.  
  224.         initialized_threads = 1;
  225.         Print(128, "starting thread");
  226.         for (proc = smp_threads + 1; proc < smp_max_threads; proc++) {
  227.           Print(128, " %d", proc);
  228.           thread[proc].tree = 0;
  229. #  if defined(UNIX)
  230.           pthread_create(&pt, &attributes, ThreadInit, (void *) proc);
  231. #  else
  232.           NumaStartThread(ThreadInit, (void *) proc);
  233. #  endif
  234.           smp_threads++;
  235.         }
  236.         Print(128, " <done>\n");
  237.       }
  238.       WaitForAllThreadsInitialized();
  239. #endif
  240.       if (search_nodes)
  241.         nodes_between_time_checks = search_nodes;
  242.       for (; iteration_depth <= MAXPLY - 5; iteration_depth++) {
  243. /*
  244.  ************************************************************
  245.  *                                                          *
  246.  *  Now install the old PV into the hash table so that      *
  247.  *  these moves will be followed first.  We do this since   *
  248.  *  the last iteration done could have overwritten the PV   *
  249.  *  as the last few root moves were searched.               *
  250.  *                                                          *
  251.  ************************************************************
  252.  */
  253.         twtm = wtm;
  254.         for (i = 1; i < (int) tree->pv[0].pathl; i++) {
  255.           if (!VerifyMove(tree, i, twtm, tree->pv[0].path[i])) {
  256.             Print(4095, "ERROR, not installing bogus pv info at ply=%d\n", i);
  257.             Print(4095, "not installing from=%d  to=%d  piece=%d\n",
  258.                 From(tree->pv[0].path[i]), To(tree->pv[0].path[i]),
  259.                 Piece(tree->pv[0].path[i]));
  260.             Print(4095, "pathlen=%d\n", tree->pv[0].pathl);
  261.             break;
  262.           }
  263.           HashStorePV(tree, twtm, i);
  264.           MakeMove(tree, i, tree->pv[0].path[i], twtm);
  265.           twtm = Flip(twtm);
  266.         }
  267.         for (i--; i > 0; i--) {
  268.           twtm = Flip(twtm);
  269.           UnmakeMove(tree, i, tree->pv[0].path[i], twtm);
  270.         }
  271. /*
  272.  ************************************************************
  273.  *                                                          *
  274.  *  Now we call Search() and start the next search          *
  275.  *  iteration.  We already have solid alpha/beta bounds set *
  276.  *  up for the aspiration search.  When each iteration      *
  277.  *  completes, these aspiration values are recomputed and   *
  278.  *  used for the next iteration.                            *
  279.  *                                                          *
  280.  *  We need to set "nodes_between_time_checks" to a value   *
  281.  *  that will force us to check the time reasonably often   *
  282.  *  without wasting excessive time doing this check.  As    *
  283.  *  the target time limit gets shorter, we shorten the      *
  284.  *  interval between time checks to avoid burning time off  *
  285.  *  of the clock unnecessarily.                             *
  286.  *                                                          *
  287.  ************************************************************
  288.  */
  289.         if (trace_level) {
  290.           printf("==================================\n");
  291.           printf("=      search iteration %2d       =\n", iteration_depth);
  292.           printf("==================================\n");
  293.         }
  294.         if (tree->nodes_searched) {
  295.           nodes_between_time_checks = nodes_per_second / 10;
  296.           if (!analyze_mode) {
  297.             if (time_limit > 300);
  298.             else if (time_limit > 50)
  299.               nodes_between_time_checks /= 10;
  300.             else
  301.               nodes_between_time_checks /= 100;
  302.           } else
  303.             nodes_between_time_checks = Min(nodes_per_second, 1000000);
  304. #if defined(SKILL)
  305.           if (skill > 50)
  306.             nodes_between_time_checks = Max(nodes_between_time_checks, 10000);
  307. #endif
  308.         }
  309.         if (search_nodes)
  310.           nodes_between_time_checks = search_nodes - (unsigned int) tree->nodes_searched; // Pierre-Marie Baty -- added type cast (FIXME: either stay on 32 bits, or port correctly!)
  311.         nodes_between_time_checks =
  312.             Min(nodes_between_time_checks, MAX_TC_NODES);
  313.         next_time_check = nodes_between_time_checks;
  314. /*
  315.  ************************************************************
  316.  *                                                          *
  317.  *  This loop will execute until we either run out of time  *
  318.  *  or complete this iteration.  Since we can return to     *
  319.  *  Iterate() multiple times during this iteration, due to  *
  320.  *  multiple fail highs (and perhaps even an initial fail   *
  321.  *  low) we stick in this loop until we have completed all  *
  322.  *  root moves or TimeCheck() tells us it is time to stop.  *
  323.  *                                                          *
  324.  ************************************************************
  325.  */
  326.         failhi_delta = 16;
  327.         faillo_delta = 16;
  328.         while (1) {
  329.           thread[0].tree = block[0];
  330.           tree->inchk[1] = Check(wtm);
  331.           if (smp_max_threads > 1)
  332.             smp_split = 1;
  333.           tree->rep_index--;
  334.           value =
  335.               Search(tree, root_alpha, root_beta, wtm, iteration_depth, 1, 0);
  336.           tree->rep_index++;
  337.           end_time = ReadClock();
  338.           if (abort_search)
  339.             break;
  340.           old_root_alpha = root_alpha;
  341.           old_root_beta = root_beta;
  342. /*
  343.  ************************************************************
  344.  *                                                          *
  345.  *  Check for the case where we get a score back that is    *
  346.  *  greater than or equal to beta.  This is called a fail   *
  347.  *  high condition and requires a re-search with a better   *
  348.  *  (more optimistic) beta value so that we can discover    *
  349.  *  just how good this move really is.                      *
  350.  *                                                          *
  351.  *  Note that each time we return here, we need to increase *
  352.  *  the upper search bound (beta).  We have a value named   *
  353.  *  failhi_delta that is initially set to 16 on the first   *
  354.  *  fail high of a particular move.  We increase beta by    *
  355.  *  this value each time we fail high.  However, each time  *
  356.  *  we fail high, we also double this value so that we      *
  357.  *  increase beta at an ever-increasing rate.  Small jumps  *
  358.  *  at first let us detect marginal score increases while   *
  359.  *  still allowing cutoffs for branches with excessively    *
  360.  *  high scores.  But each re-search sees the margin double *
  361.  *  which quickly increases the bound as needed.            *
  362.  *                                                          *
  363.  *  We also use ComputeDifficulty() to adjust the level of  *
  364.  *  difficulty for this move since we might be changing our *
  365.  *  mind at the root.  (If we are failing high on the first *
  366.  *  root move we skip this update.)                         *
  367.  *                                                          *
  368.  ************************************************************
  369.  */
  370.           if (value >= root_beta) {
  371.             root_beta = Min(old_root_beta + failhi_delta, MATE);
  372.             failhi_delta *= 2;
  373.             if (failhi_delta > 10 * PAWN_VALUE)
  374.               failhi_delta = 99999;
  375.             root_moves[0].status &= 0xf7;
  376.             if ((root_moves[0].status & 2) == 0)
  377.               difficulty = ComputeDifficulty(difficulty, +1);
  378.             root_moves[0].status |= 2;
  379.             if (tree->nodes_searched > noise_level) {
  380.               fh_indicator = (wtm) ? "++" : "--";
  381.               Print(2, "         %2i   %s     %2s   ", iteration_depth,
  382.                   Display2Times(end_time - start_time), fh_indicator);
  383.               if (display_options & 64)
  384.                 Print(2, "%d. ", move_number);
  385.               if ((display_options & 64) && !wtm)
  386.                 Print(2, "... ");
  387.               Print(2, "%s! ", OutputMove(tree, tree->pv[1].path[1], 1, wtm));
  388.               Print(2, "(%c%s)                  \n", (wtm) ? '>' : '<',
  389.                   DisplayEvaluationKibitz(old_root_beta, wtm));
  390.               kibitz_text[0] = 0;
  391.               if (display_options & 64)
  392.                 sprintf_s(kibitz_text, sizeof (kibitz_text), " %d.", move_number); // Pierre-Marie Baty -- use safe version
  393.               if ((display_options & 64) && !wtm)
  394.                 strcat_s(kibitz_text, sizeof (kibitz_text), " ..."); // Pierre-Marie Baty -- use safe version
  395.               sprintf(kibitz_text + strlen(kibitz_text), " %s!",
  396.                   OutputMove(tree, tree->pv[1].path[1], 1, wtm));
  397.               idle_percent =
  398.                   100 - Min(100,
  399.                   100 * idle_time / (smp_max_threads * (end_time -
  400.                           start_time) + 1));
  401.               Kibitz(6, wtm, iteration_depth, end_time - start_time, value,
  402.                   tree->nodes_searched, idle_percent,
  403.                   tree->egtb_probes_successful, kibitz_text);
  404.             }
  405. /*
  406.  ************************************************************
  407.  *                                                          *
  408.  *  Check for the case where we get a score back that is    *
  409.  *  less than or equal to alpha.  This is called a fail     *
  410.  *  low condition and requires a re-search with a better    *
  411.  *  more pessimistic)) alpha value so that we can discover  *
  412.  *  just how bad this move really is.                       *
  413.  *                                                          *
  414.  *  Note that each time we return here, we need to decrease *
  415.  *  the lower search bound (alpha).  We have a value named  *
  416.  *  faillo_delta that is initially set to 16 on the first   *
  417.  *  fail low of a particular move.  We decrease alpha by    *
  418.  *  this value each time we fail low.  However, each time   *
  419.  *  we fail low, we also double this value so that we       *
  420.  *  decrease alpha at an ever-increasing rate.  Small jumps *
  421.  *  at first let us detect marginal score decreases while   *
  422.  *  still allowing cutoffs for branches with excessively    *
  423.  *  low scores.  But each re-search sees the margin double  *
  424.  *  which quickly decreases the bound as needed.            *
  425.  *                                                          *
  426.  *  We also use ComputeDifficulty() to adjust the level of  *
  427.  *  difficulty for this move since we are failing low on    *
  428.  *  the first move at the root, and we don't want to stop   *
  429.  *  before we have a chance to find a better one.           *
  430.  *                                                          *
  431.  ************************************************************
  432.  */
  433.           } else if (value <= root_alpha) {
  434.             root_alpha = Max(old_root_alpha - faillo_delta, -MATE);
  435.             faillo_delta *= 2;
  436.             if (faillo_delta > 10 * PAWN_VALUE)
  437.               faillo_delta = 99999;
  438.             root_moves[0].status &= 0xf7;
  439.             if ((root_moves[0].status & 1) == 0)
  440.               difficulty = ComputeDifficulty(Max(100, difficulty), -1);
  441.             root_moves[0].status |= 1;
  442.             if (tree->nodes_searched > noise_level && !abort_search) {
  443.               fl_indicator = (wtm) ? "--" : "++";
  444.               Print(4, "         %2i   %s     %2s   ", iteration_depth,
  445.                   Display2Times(ReadClock() - start_time), fl_indicator);
  446.               if (display_options & 64)
  447.                 Print(4, "%d. ", move_number);
  448.               if ((display_options & 64) && !wtm)
  449.                 Print(4, "... ");
  450.               Print(4, "%s? ", OutputMove(tree, root_moves[0].move, 1, wtm));
  451.               Print(4, "(%c%s)                  \n", (Flip(wtm)) ? '>' : '<',
  452.                   DisplayEvaluationKibitz(old_root_alpha, wtm));
  453.             }
  454.           } else
  455.             break;
  456.         }
  457.         if (value > root_alpha && value < root_beta)
  458.           last_root_value = value;
  459. /*
  460.  ************************************************************
  461.  *                                                          *
  462.  *  If we are running a test suite, check to see if we can  *
  463.  *  exit the search.  This happens when N successive        *
  464.  *  iterations produce the correct solution.  N is set by   *
  465.  *  the test command in Option().                           *
  466.  *                                                          *
  467.  ************************************************************
  468.  */
  469.         correct = solution_type;
  470.         for (i = 0; i < number_of_solutions; i++) {
  471.           if (!solution_type) {
  472.             if (solutions[i] == tree->pv[0].path[1])
  473.               correct = 1;
  474.           } else if (solutions[i] == tree->pv[0].path[1])
  475.             correct = 0;
  476.         }
  477.         if (correct)
  478.           correct_count++;
  479.         else
  480.           correct_count = 0;
  481. /*
  482.  ************************************************************
  483.  *                                                          *
  484.  *  Notice that we don't search moves that were best over   *
  485.  *  the last 3 iterations in parallel, nor do we reduce     *
  486.  *  those since they are potential best moves again.        *
  487.  *                                                          *
  488.  ************************************************************
  489.  */
  490.         for (i = 0; i < n_root_moves; i++) {
  491.           if (root_moves[i].bm_age)
  492.             root_moves[i].bm_age--;
  493.           if (root_moves[i].bm_age)
  494.             root_moves[i].status &= 0xfb;
  495.           else
  496.             root_moves[i].status |= 4;
  497.         }
  498.         difficulty = ComputeDifficulty(difficulty, 0);
  499. /*
  500.  ************************************************************
  501.  *                                                          *
  502.  *  If requested, print the ply=1 move list along with the  *
  503.  *  flags for each move.  Once we print this (if requested) *
  504.  *  we can then clear all of the status flags (except the   *
  505.  *  "ok to search in parallel or reduce" flag) to prepare   *
  506.  *  for the start of the next iteration, since that is the  *
  507.  *  only flag that needs to be carried forward to the next  *
  508.  *  iteration.                                              *
  509.  *                                                          *
  510.  ************************************************************
  511.  */
  512.         if (display_options & 256) {
  513.           Print(128, "       move  age  R ! ?\n");
  514.           for (i = 0; i < n_root_moves; i++) {
  515.             Print(128, " %10s   %d   %d %d %d\n", OutputMove(tree,
  516.                     root_moves[i].move, 1, wtm), root_moves[i].bm_age,
  517.                 (root_moves[i].status & 4) != 0,
  518.                 (root_moves[i].status & 2) != 0,
  519.                 (root_moves[i].status & 1) != 0);
  520.           }
  521.         }
  522.         for (i = 0; i < n_root_moves; i++)
  523.           root_moves[i].status &= 4;
  524. /*
  525.  ************************************************************
  526.  *                                                          *
  527.  *  Here we simply display the PV from the current search   *
  528.  *  iteration, and then set the aspiration for the next     *
  529.  *  iteration to the current score +/- 16.                  *
  530.  *                                                          *
  531.  ************************************************************
  532.  */
  533.         if (end_time - start_time > 10)
  534.           nodes_per_second =
  535.               (unsigned int) (tree->nodes_searched * 100 / (end_time - start_time)); // Pierre-Marie Baty -- added type cast (FIXME: either stay on 32 bits, or port correctly!)
  536.         else
  537.           nodes_per_second = 1000000;
  538.         if (!abort_search && value != -(MATE - 1)) {
  539.           if (tree->nodes_searched > noise_level) {
  540.             DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0]);
  541.             noise_block = 0;
  542.           }
  543.         }
  544.         root_alpha = Max(-MATE, value - 16);
  545.         root_beta = Min(MATE, value + 16);
  546. /*
  547.  ************************************************************
  548.  *                                                          *
  549.  *  There are multiple termination criteria that are used.  *
  550.  *  The first and most obvious is that we have exceeded the *
  551.  *  target time limit.  Others include reaching a user-set  *
  552.  *  maximum search depth, finding a mate and we searched so *
  553.  *  deep there is little chance of another iteration find-  *
  554.  *  ing a shorter mate; the search was aborted due to some  *
  555.  *  sort of user input (usually during pondering);  and     *
  556.  *  finally, when running a test suite, we had the correct  *
  557.  *  best move for N successive iterations and the user      *
  558.  *  asked us to stop after that number.                     *
  559.  *                                                          *
  560.  ************************************************************
  561.  */
  562.         if (TimeCheck(tree, 0))
  563.           break;
  564.         if (iteration_depth > 3 && value > 32000 &&
  565.             value >= (MATE - iteration_depth + 3)
  566.             && value > last_mate_score)
  567.           break;
  568.         if ((iteration_depth >= search_depth) && search_depth)
  569.           break;
  570.         if (abort_search)
  571.           break;
  572.         end_time = ReadClock() - start_time;
  573.         if (correct_count >= early_exit)
  574.           break;
  575. #if !defined(NOEGTB)
  576.         if (iteration_depth > 10 && TotalAllPieces <= EGTBlimit && EGTB_use &&
  577.             !EGTB_search && EGTBProbe(tree, 1, wtm, &i))
  578.           break;
  579. #endif
  580.         if (search_nodes && tree->nodes_searched >= search_nodes)
  581.           break;
  582.       }
  583. /*
  584.  ************************************************************
  585.  *                                                          *
  586.  *  Search done, now display statistics, depending on the   *
  587.  *  display options set (see display command in Option().)  *
  588.  *                                                          *
  589.  *  Simple kludge here.  If the last search was quite deep  *
  590.  *  while we were pondering, we start this iteration at the *
  591.  *  last depth - 1.  Sometimes that will result in a search *
  592.  *  that is deep enough that we do not produce/print a PV   *
  593.  *  before time runs out.  On other occasions, noise_level  *
  594.  *  prevents us from printing anything, leaving us with no  *
  595.  *  output during this PV.  We initialize a variable named  *
  596.  *  noise_block to 1.  If, during this iteration, we do     *
  597.  *  manage to print a PV, we set it to zero until the next  *
  598.  *  iteration starts.  Otherwise this will force us to at   *
  599.  *  display the PV from the last iteration (first two moves *
  600.  *  were removed in main(), so they are not present) so we  *
  601.  *  have some sort of output for this iteration.            *
  602.  *                                                          *
  603.  ************************************************************
  604.  */
  605.       end_time = ReadClock();
  606.       if (end_time > 10)
  607.         nodes_per_second =
  608.             (unsigned int) (tree->nodes_searched * 100 / (end_time -
  609.             start_time + 1)); // Pierre-Marie Baty -- added type cast (FIXME: either stay on 32 bits, or port correctly!)
  610.       if (abort_search != 2 && !puzzling) {
  611.         if (noise_block)
  612.           DisplayPV(tree, 5, wtm, end_time - start_time, &tree->pv[0]);
  613.         tree->evaluations = (tree->evaluations) ? tree->evaluations : 1;
  614.         tree->fail_highs++;
  615.         tree->fail_high_first_move++;
  616.         idle_percent =
  617.             100 - Min(100,
  618.             100 * idle_time / (smp_max_threads * (end_time - start_time) +
  619.                 1));
  620.         Print(8, "        time=%s(%d%%)",
  621.             DisplayTimeKibitz(end_time - start_time), idle_percent);
  622.         Print(8, "  n=%" PRIu64, tree->nodes_searched);
  623.         Print(8, "  fh1=%d%%",
  624.             tree->fail_high_first_move * 100 / tree->fail_highs);
  625.         Print(8, "  50move=%d", Reversible(0));
  626.         Print(8, "  nps=%s\n", DisplayKMB(nodes_per_second));
  627.         Print(16, "        ext=%s", DisplayKMB(tree->extensions_done));
  628.         Print(16, "  red=%s", DisplayKMB(tree->reductions_done));
  629.         Print(16, "  pruned=%s", DisplayKMB(tree->moves_fpruned));
  630.         Print(16, "  qchks=%s", DisplayKMB(tree->qchecks_done));
  631.         Print(16, "  pred=%d\n", predicted);
  632.         Print(16, "        splits=%s", DisplayKMB(parallel_splits));
  633.         Print(16, "  aborts=%s", DisplayKMB(parallel_aborts));
  634.         Print(16, "  data=%d%%", 100 * max_split_blocks / Max(MAX_BLOCKS, 1));
  635.         Print(16, "  probes=%s", DisplayKMB(tree->egtb_probes));
  636.         Print(16, "  hits=%s\n", DisplayKMB(tree->egtb_probes_successful));
  637.       }
  638.     } while (0);
  639. /*
  640.  ************************************************************
  641.  *                                                          *
  642.  *  If this is a known book position, Book() has already    *
  643.  *  set the PV/best move so we can return without doing the *
  644.  *  iterated search at all.                                 *
  645.  *                                                          *
  646.  ************************************************************
  647.  */
  648.   else {
  649.     last_root_value = 0;
  650.     value = 0;
  651.     book_move = 1;
  652.     tree->pv[0] = tree->pv[1];
  653.     if (analyze_mode)
  654.       Kibitz(4, wtm, 0, 0, 0, 0, 0, 0, kibitz_text);
  655.   }
  656. /*
  657.  ************************************************************
  658.  *                                                          *
  659.  *  If "smp_nice" is set, and we are not allowed to ponder  *
  660.  *  while waiting on the opponent to move, then terminate   *
  661.  *  the parallel threads so they won't sit in their normal  *
  662.  *  spin-wait loop while waiting for new work which will    *
  663.  *  "burn" smp_max_threads - 1 cpus, penalizing anything    *
  664.  *  else that might be running (such as another chess       *
  665.  *  engine we might be playing in a ponder=off match.)      *
  666.  *                                                          *
  667.  ************************************************************
  668.  */
  669.   if (smp_nice && ponder == 0 && smp_threads) {
  670.     int proc;
  671.     Print(128, "terminating SMP processes.\n");
  672.     for (proc = 1; proc < CPUS; proc++)
  673.       thread[proc].tree = (TREE *) - 1;
  674.     while (smp_threads);
  675.     smp_idle = 0;
  676.     smp_split = 0;
  677.   }
  678.   program_end_time = ReadClock();
  679.   search_move = 0;
  680.   if (quit)
  681.     CraftyExit(0);
  682.   return last_root_value;
  683. }
  684.