Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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