Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Rev 154 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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