Subversion Repositories Games.Chess Giants

Rev

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

Rev 169 Rev 185
Line 4... Line 4...
4
  Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
4
  Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
  Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
5
  Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
 
6
 
7
  Stockfish is free software: you can redistribute it and/or modify
7
  Stockfish is free software: you can redistribute it and/or modify
8
  it under the terms of the GNU General Public License as published by
8
  it under the terms of the GNU General Public License as published by
9
  the Free Software Foundation, either version 3 of the License, or
9
  the Free Software Foundation, either version 3 of the License, or
10
  (at your option) any later version.
10
  (at your option) any later version.
Line 33... Line 33...
33
#include "tt.h"
33
#include "tt.h"
34
#include "uci.h"
34
#include "uci.h"
35
#include "syzygy/tbprobe.h"
35
#include "syzygy/tbprobe.h"
36
 
36
 
37
using std::string;
37
using std::string;
38
 
-
 
39
namespace PSQT {
-
 
40
  extern Score psq[PIECE_NB][SQUARE_NB];
-
 
41
}
-
 
42
 
38
 
43
namespace Zobrist {
39
namespace Zobrist {
44
 
40
 
45
  Key psq[PIECE_NB][SQUARE_NB];
41
  Key psq[PIECE_NB][SQUARE_NB];
46
  Key enpassant[FILE_NB];
42
  Key enpassant[FILE_NB];
Line 50... Line 46...
50
 
46
 
51
namespace {
47
namespace {
52
 
48
 
53
const string PieceToChar(" PNBRQK  pnbrqk");
49
const string PieceToChar(" PNBRQK  pnbrqk");
54
 
50
 
55
const Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
51
constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
56
                         B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
52
                             B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
57
 
53
 
58
// min_attacker() is a helper function used by see_ge() to locate the least
54
// min_attacker() is a helper function used by see_ge() to locate the least
59
// valuable attacker for the side to move, remove the attacker we just found
55
// valuable attacker for the side to move, remove the attacker we just found
60
// from the bitboards and scan for new X-ray attacks behind it.
56
// from the bitboards and scan for new X-ray attacks behind it.
61
 
57
 
62
template<int Pt>
58
template<int Pt>
63
PieceType min_attacker(const Bitboard* bb, Square to, Bitboard stmAttackers,
59
PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers,
64
                       Bitboard& occupied, Bitboard& attackers) {
60
                       Bitboard& occupied, Bitboard& attackers) {
65
 
61
 
66
  Bitboard b = stmAttackers & bb[Pt];
62
  Bitboard b = stmAttackers & byTypeBB[Pt];
67
  if (!b)
63
  if (!b)
68
      return min_attacker<Pt + 1>(bb, to, stmAttackers, occupied, attackers);
64
      return min_attacker<Pt + 1>(byTypeBB, to, stmAttackers, occupied, attackers);
69
 
65
 
70
  occupied ^= b & ~(b - 1);
66
  occupied ^= lsb(b); // Remove the attacker from occupied
71
 
67
 
-
 
68
  // Add any X-ray attack behind the just removed piece. For instance with
-
 
69
  // rooks in a8 and a7 attacking a1, after removing a7 we add rook in a8.
-
 
70
  // Note that new added attackers can be of any color.
72
  if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
71
  if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
73
      attackers |= attacks_bb<BISHOP>(to, occupied) & (bb[BISHOP] | bb[QUEEN]);
72
      attackers |= attacks_bb<BISHOP>(to, occupied) & (byTypeBB[BISHOP] | byTypeBB[QUEEN]);
74
 
73
 
75
  if (Pt == ROOK || Pt == QUEEN)
74
  if (Pt == ROOK || Pt == QUEEN)
76
      attackers |= attacks_bb<ROOK>(to, occupied) & (bb[ROOK] | bb[QUEEN]);
75
      attackers |= attacks_bb<ROOK>(to, occupied) & (byTypeBB[ROOK] | byTypeBB[QUEEN]);
77
 
76
 
-
 
77
  // X-ray may add already processed pieces because byTypeBB[] is constant: in
78
  attackers &= occupied; // After X-ray that may add already processed pieces
78
  // the rook example, now attackers contains _again_ rook in a7, so remove it.
-
 
79
  attackers &= occupied;
79
  return (PieceType)Pt;
80
  return (PieceType)Pt;
80
}
81
}
81
 
82
 
82
template<>
83
template<>
83
PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) {
84
PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) {
Line 121... Line 122...
121
         << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")";
122
         << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")";
122
  }
123
  }
123
 
124
 
124
  return os;
125
  return os;
125
}
126
}
-
 
127
 
-
 
128
 
-
 
129
// Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition"
-
 
130
// situations. Description of the algorithm in the following paper:
-
 
131
// https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf
-
 
132
 
-
 
133
// First and second hash functions for indexing the cuckoo tables
-
 
134
inline int H1(Key h) { return h & 0x1fff; }
-
 
135
inline int H2(Key h) { return (h >> 16) & 0x1fff; }
-
 
136
 
-
 
137
// Cuckoo tables with Zobrist hashes of valid reversible moves, and the moves themselves
-
 
138
Key cuckoo[8192];
-
 
139
Move cuckooMove[8192];
126
 
140
 
127
 
141
 
128
/// Position::init() initializes at startup the various arrays used to compute
142
/// Position::init() initializes at startup the various arrays used to compute
129
/// hash keys.
143
/// hash keys.
130
 
144
 
Line 150... Line 164...
150
      }
164
      }
151
  }
165
  }
152
 
166
 
153
  Zobrist::side = rng.rand<Key>();
167
  Zobrist::side = rng.rand<Key>();
154
  Zobrist::noPawns = rng.rand<Key>();
168
  Zobrist::noPawns = rng.rand<Key>();
-
 
169
 
-
 
170
  // Prepare the cuckoo tables
-
 
171
  std::memset(cuckoo, 0, sizeof(cuckoo));
-
 
172
  std::memset(cuckooMove, 0, sizeof(cuckooMove));
-
 
173
  int count = 0;
-
 
174
  for (Piece pc : Pieces)
-
 
175
      for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
-
 
176
          for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2)
-
 
177
              if (PseudoAttacks[type_of(pc)][s1] & s2)
-
 
178
              {
-
 
179
                  Move move = make_move(s1, s2);
-
 
180
                  Key key = Zobrist::psq[pc][s1] ^ Zobrist::psq[pc][s2] ^ Zobrist::side;
-
 
181
                  int i = H1(key);
-
 
182
                  while (true)
-
 
183
                  {
-
 
184
                      std::swap(cuckoo[i], key);
-
 
185
                      std::swap(cuckooMove[i], move);
-
 
186
                      if (move == 0)   // Arrived at empty slot ?
-
 
187
                          break;
-
 
188
                      i = (i == H1(key)) ? H2(key) : H1(key); // Push victim to alternative slot
-
 
189
                  }
-
 
190
                  count++;
-
 
191
             }
-
 
192
  assert(count == 3668);
155
}
193
}
156
 
194
 
157
 
195
 
158
/// Position::set() initializes the position object with the given FEN string.
196
/// Position::set() initializes the position object with the given FEN string.
159
/// This function is not very robust - make sure that input FENs are correct,
197
/// This function is not very robust - make sure that input FENs are correct,
Line 315... Line 353...
315
 
353
 
316
/// Position::set_check_info() sets king attacks to detect if a move gives check
354
/// Position::set_check_info() sets king attacks to detect if a move gives check
317
 
355
 
318
void Position::set_check_info(StateInfo* si) const {
356
void Position::set_check_info(StateInfo* si) const {
319
 
357
 
320
  si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinnersForKing[WHITE]);
358
  si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinners[BLACK]);
321
  si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinnersForKing[BLACK]);
359
  si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinners[WHITE]);
322
 
360
 
323
  Square ksq = square<KING>(~sideToMove);
361
  Square ksq = square<KING>(~sideToMove);
324
 
362
 
325
  si->checkSquares[PAWN]   = attacks_from<PAWN>(ksq, ~sideToMove);
363
  si->checkSquares[PAWN]   = attacks_from<PAWN>(ksq, ~sideToMove);
326
  si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
364
  si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
Line 339... Line 377...
339
void Position::set_state(StateInfo* si) const {
377
void Position::set_state(StateInfo* si) const {
340
 
378
 
341
  si->key = si->materialKey = 0;
379
  si->key = si->materialKey = 0;
342
  si->pawnKey = Zobrist::noPawns;
380
  si->pawnKey = Zobrist::noPawns;
343
  si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO;
381
  si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO;
344
  si->psq = SCORE_ZERO;
-
 
345
  si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
382
  si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
346
 
383
 
347
  set_check_info(si);
384
  set_check_info(si);
348
 
385
 
349
  for (Bitboard b = pieces(); b; )
386
  for (Bitboard b = pieces(); b; )
350
  {
387
  {
351
      Square s = pop_lsb(&b);
388
      Square s = pop_lsb(&b);
352
      Piece pc = piece_on(s);
389
      Piece pc = piece_on(s);
353
      si->key ^= Zobrist::psq[pc][s];
390
      si->key ^= Zobrist::psq[pc][s];
354
      si->psq += PSQT::psq[pc][s];
-
 
355
  }
391
  }
356
 
392
 
357
  if (si->epSquare != SQ_NONE)
393
  if (si->epSquare != SQ_NONE)
358
      si->key ^= Zobrist::enpassant[file_of(si->epSquare)];
394
      si->key ^= Zobrist::enpassant[file_of(si->epSquare)];
359
 
395
 
Line 457... Line 493...
457
/// a pinned or a discovered check piece, according if its color is the opposite
493
/// a pinned or a discovered check piece, according if its color is the opposite
458
/// or the same of the color of the slider.
494
/// or the same of the color of the slider.
459
 
495
 
460
Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
496
Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
461
 
497
 
462
  Bitboard result = 0;
498
  Bitboard blockers = 0;
463
  pinners = 0;
499
  pinners = 0;
464
 
500
 
465
  // Snipers are sliders that attack 's' when a piece is removed
501
  // Snipers are sliders that attack 's' when a piece is removed
466
  Bitboard snipers = (  (PseudoAttacks[  ROOK][s] & pieces(QUEEN, ROOK))
502
  Bitboard snipers = (  (PseudoAttacks[  ROOK][s] & pieces(QUEEN, ROOK))
467
                      | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
503
                      | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
Line 469... Line 505...
469
  while (snipers)
505
  while (snipers)
470
  {
506
  {
471
    Square sniperSq = pop_lsb(&snipers);
507
    Square sniperSq = pop_lsb(&snipers);
472
    Bitboard b = between_bb(s, sniperSq) & pieces();
508
    Bitboard b = between_bb(s, sniperSq) & pieces();
473
 
509
 
474
    if (!more_than_one(b))
510
    if (b && !more_than_one(b))
475
    {
511
    {
476
        result |= b;
512
        blockers |= b;
477
        if (b & pieces(color_of(piece_on(s))))
513
        if (b & pieces(color_of(piece_on(s))))
478
            pinners |= sniperSq;
514
            pinners |= sniperSq;
479
    }
515
    }
480
  }
516
  }
481
  return result;
517
  return blockers;
482
}
518
}
483
 
519
 
484
 
520
 
485
/// Position::attackers_to() computes a bitboard of all pieces which attack a
521
/// Position::attackers_to() computes a bitboard of all pieces which attack a
486
/// given square. Slider attacks use the occupied bitboard to indicate occupancy.
522
/// given square. Slider attacks use the occupied bitboard to indicate occupancy.
Line 533... Line 569...
533
  if (type_of(piece_on(from)) == KING)
569
  if (type_of(piece_on(from)) == KING)
534
      return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us));
570
      return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us));
535
 
571
 
536
  // A non-king move is legal if and only if it is not pinned or it
572
  // A non-king move is legal if and only if it is not pinned or it
537
  // is moving along the ray towards or away from the king.
573
  // is moving along the ray towards or away from the king.
538
  return   !(pinned_pieces(us) & from)
574
  return   !(blockers_for_king(us) & from)
539
        ||  aligned(from, to_sq(m), square<KING>(us));
575
        ||  aligned(from, to_sq(m), square<KING>(us));
540
}
576
}
541
 
577
 
542
 
578
 
543
/// Position::pseudo_legal() takes a random move and tests whether the move is
579
/// Position::pseudo_legal() takes a random move and tests whether the move is
Line 625... Line 661...
625
  // Is there a direct check?
661
  // Is there a direct check?
626
  if (st->checkSquares[type_of(piece_on(from))] & to)
662
  if (st->checkSquares[type_of(piece_on(from))] & to)
627
      return true;
663
      return true;
628
 
664
 
629
  // Is there a discovered check?
665
  // Is there a discovered check?
630
  if (   (discovered_check_candidates() & from)
666
  if (   (st->blockersForKing[~sideToMove] & from)
631
      && !aligned(from, to, square<KING>(~sideToMove)))
667
      && !aligned(from, to, square<KING>(~sideToMove)))
632
      return true;
668
      return true;
633
 
669
 
634
  switch (type_of(m))
670
  switch (type_of(m))
635
  {
671
  {
Line 710... Line 746...
710
      assert(captured == make_piece(us, ROOK));
746
      assert(captured == make_piece(us, ROOK));
711
 
747
 
712
      Square rfrom, rto;
748
      Square rfrom, rto;
713
      do_castling<true>(us, from, to, rfrom, rto);
749
      do_castling<true>(us, from, to, rfrom, rto);
714
 
750
 
715
      st->psq += PSQT::psq[captured][rto] - PSQT::psq[captured][rfrom];
-
 
716
      k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
751
      k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
717
      captured = NO_PIECE;
752
      captured = NO_PIECE;
718
  }
753
  }
719
 
754
 
720
  if (captured)
755
  if (captured)
Line 748... Line 783...
748
 
783
 
749
      // Update material hash key and prefetch access to materialTable
784
      // Update material hash key and prefetch access to materialTable
750
      k ^= Zobrist::psq[captured][capsq];
785
      k ^= Zobrist::psq[captured][capsq];
751
      st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
786
      st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
752
      prefetch(thisThread->materialTable[st->materialKey]);
787
      prefetch(thisThread->materialTable[st->materialKey]);
753
 
-
 
754
      // Update incremental scores
-
 
755
      st->psq -= PSQT::psq[captured][capsq];
-
 
756
 
788
 
757
      // Reset rule 50 counter
789
      // Reset rule 50 counter
758
      st->rule50 = 0;
790
      st->rule50 = 0;
759
  }
791
  }
760
 
792
 
Line 804... Line 836...
804
          // Update hash keys
836
          // Update hash keys
805
          k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
837
          k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
806
          st->pawnKey ^= Zobrist::psq[pc][to];
838
          st->pawnKey ^= Zobrist::psq[pc][to];
807
          st->materialKey ^=  Zobrist::psq[promotion][pieceCount[promotion]-1]
839
          st->materialKey ^=  Zobrist::psq[promotion][pieceCount[promotion]-1]
808
                            ^ Zobrist::psq[pc][pieceCount[pc]];
840
                            ^ Zobrist::psq[pc][pieceCount[pc]];
809
 
-
 
810
          // Update incremental score
-
 
811
          st->psq += PSQT::psq[promotion][to] - PSQT::psq[pc][to];
-
 
812
 
841
 
813
          // Update material
842
          // Update material
814
          st->nonPawnMaterial[us] += PieceValue[MG][promotion];
843
          st->nonPawnMaterial[us] += PieceValue[MG][promotion];
815
      }
844
      }
816
 
845
 
Line 819... Line 848...
819
      prefetch2(thisThread->pawnsTable[st->pawnKey]);
848
      prefetch2(thisThread->pawnsTable[st->pawnKey]);
820
 
849
 
821
      // Reset rule 50 draw counter
850
      // Reset rule 50 draw counter
822
      st->rule50 = 0;
851
      st->rule50 = 0;
823
  }
852
  }
824
 
-
 
825
  // Update incremental scores
-
 
826
  st->psq += PSQT::psq[pc][to] - PSQT::psq[pc][from];
-
 
827
 
853
 
828
  // Set capture piece
854
  // Set capture piece
829
  st->capturedPiece = captured;
855
  st->capturedPiece = captured;
830
 
856
 
831
  // Update the key with the final value
857
  // Update the key with the final value
Line 995... Line 1021...
995
 
1021
 
996
  // Only deal with normal moves, assume others pass a simple see
1022
  // Only deal with normal moves, assume others pass a simple see
997
  if (type_of(m) != NORMAL)
1023
  if (type_of(m) != NORMAL)
998
      return VALUE_ZERO >= threshold;
1024
      return VALUE_ZERO >= threshold;
999
 
1025
 
-
 
1026
  Bitboard stmAttackers;
1000
  Square from = from_sq(m), to = to_sq(m);
1027
  Square from = from_sq(m), to = to_sq(m);
1001
  PieceType nextVictim = type_of(piece_on(from));
1028
  PieceType nextVictim = type_of(piece_on(from));
-
 
1029
  Color us = color_of(piece_on(from));
1002
  Color stm = ~color_of(piece_on(from)); // First consider opponent's move
1030
  Color stm = ~us; // First consider opponent's move
1003
  Value balance; // Values of the pieces taken by us minus opponent's ones
1031
  Value balance;   // Values of the pieces taken by us minus opponent's ones
1004
  Bitboard occupied, stmAttackers;
-
 
1005
 
1032
 
1006
  // The opponent may be able to recapture so this is the best result
1033
  // The opponent may be able to recapture so this is the best result
1007
  // we can hope for.
1034
  // we can hope for.
1008
  balance = PieceValue[MG][piece_on(to)] - threshold;
1035
  balance = PieceValue[MG][piece_on(to)] - threshold;
1009
 
1036
 
Line 1012... Line 1039...
1012
 
1039
 
1013
  // Now assume the worst possible result: that the opponent can
1040
  // Now assume the worst possible result: that the opponent can
1014
  // capture our piece for free.
1041
  // capture our piece for free.
1015
  balance -= PieceValue[MG][nextVictim];
1042
  balance -= PieceValue[MG][nextVictim];
1016
 
1043
 
-
 
1044
  // If it is enough (like in PxQ) then return immediately. Note that
1017
  if (balance >= VALUE_ZERO) // Always true if nextVictim == KING
1045
  // in case nextVictim == KING we always return here, this is ok
-
 
1046
  // if the given move is legal.
-
 
1047
  if (balance >= VALUE_ZERO)
1018
      return true;
1048
      return true;
1019
 
1049
 
1020
  bool opponentToMove = true;
-
 
1021
  occupied = pieces() ^ from ^ to;
-
 
1022
 
-
 
1023
  // Find all attackers to the destination square, with the moving piece removed,
1050
  // Find all attackers to the destination square, with the moving piece
1024
  // but possibly an X-ray attacker added behind it.
1051
  // removed, but possibly an X-ray attacker added behind it.
-
 
1052
  Bitboard occupied = pieces() ^ from ^ to;
1025
  Bitboard attackers = attackers_to(to, occupied) & occupied;
1053
  Bitboard attackers = attackers_to(to, occupied) & occupied;
1026
 
1054
 
1027
  while (true)
1055
  while (true)
1028
  {
1056
  {
1029
      // The balance is negative only because we assumed we could win
-
 
1030
      // the last piece for free. We are truly winning only if we can
-
 
1031
      // win the last piece _cheaply enough_. Test if we can actually
-
 
1032
      // do this otherwise "give up".
-
 
1033
      assert(balance < VALUE_ZERO);
-
 
1034
 
-
 
1035
      stmAttackers = attackers & pieces(stm);
1057
      stmAttackers = attackers & pieces(stm);
1036
 
1058
 
1037
      // Don't allow pinned pieces to attack pieces except the king as long all
1059
      // Don't allow pinned pieces to attack (except the king) as long as
1038
      // pinners are on their original square.
1060
      // all pinners are on their original square.
1039
      if (!(st->pinnersForKing[stm] & ~occupied))
1061
      if (!(st->pinners[~stm] & ~occupied))
1040
          stmAttackers &= ~st->blockersForKing[stm];
1062
          stmAttackers &= ~st->blockersForKing[stm];
1041
 
1063
 
1042
      // If we have no more attackers we must give up
1064
      // If stm has no more attackers then give up: stm loses
1043
      if (!stmAttackers)
1065
      if (!stmAttackers)
1044
          break;
1066
          break;
1045
 
1067
 
1046
      // Locate and remove the next least valuable attacker
1068
      // Locate and remove the next least valuable attacker, and add to
-
 
1069
      // the bitboard 'attackers' the possibly X-ray attackers behind it.
1047
      nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
1070
      nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
1048
 
1071
 
1049
      if (nextVictim == KING)
-
 
1050
      {
-
 
1051
          // Our only attacker is the king. If the opponent still has
-
 
1052
          // attackers we must give up. Otherwise we make the move and
-
 
1053
          // (having no more attackers) the opponent must give up.
-
 
1054
          if (!(attackers & pieces(~stm)))
1072
      stm = ~stm; // Switch side to move
1055
              opponentToMove = !opponentToMove;
-
 
1056
          break;
-
 
1057
      }
-
 
1058
 
1073
 
1059
      // Assume the opponent can win the next piece for free and switch sides
1074
      // Negamax the balance with alpha = balance, beta = balance+1 and
-
 
1075
      // add nextVictim's value.
-
 
1076
      //
1060
      balance += PieceValue[MG][nextVictim];
1077
      //      (balance, balance+1) -> (-balance-1, -balance)
-
 
1078
      //
1061
      opponentToMove = !opponentToMove;
1079
      assert(balance < VALUE_ZERO);
1062
 
1080
 
1063
      // If balance is negative after receiving a free piece then give up
1081
      balance = -balance - 1 - PieceValue[MG][nextVictim];
1064
      if (balance < VALUE_ZERO)
-
 
1065
          break;
-
 
1066
 
1082
 
1067
      // Complete the process of switching sides. The first line swaps
1083
      // If balance is still non-negative after giving away nextVictim then we
1068
      // all negative numbers with non-negative numbers. The compiler
1084
      // win. The only thing to be careful about it is that we should revert
1069
      // probably knows that it is just the bitwise negation ~balance.
1085
      // stm if we captured with the king when the opponent still has attackers.
1070
      balance = -balance-1;
1086
      if (balance >= VALUE_ZERO)
-
 
1087
      {
-
 
1088
          if (nextVictim == KING && (attackers & pieces(stm)))
1071
      stm = ~stm;
1089
              stm = ~stm;
-
 
1090
          break;
-
 
1091
      }
-
 
1092
      assert(nextVictim != KING);
1072
  }
1093
  }
1073
 
-
 
1074
  // If the opponent gave up we win, otherwise we lose.
1094
  return us != stm; // We break the above loop when stm loses
1075
  return opponentToMove;
-
 
1076
}
1095
}
1077
 
1096
 
1078
 
1097
 
1079
/// Position::is_draw() tests whether the position is drawn by 50-move rule
1098
/// Position::is_draw() tests whether the position is drawn by 50-move rule
1080
/// or by repetition. It does not detect stalemates.
1099
/// or by repetition. It does not detect stalemates.
Line 1101... Line 1120...
1101
      if (   stp->key == st->key
1120
      if (   stp->key == st->key
1102
          && ++cnt + (ply > i) == 2)
1121
          && ++cnt + (ply > i) == 2)
1103
          return true;
1122
          return true;
1104
  }
1123
  }
1105
 
1124
 
-
 
1125
  return false;
-
 
1126
}
-
 
1127
 
-
 
1128
 
-
 
1129
// Position::has_repeated() tests whether there has been at least one repetition
-
 
1130
// of positions since the last capture or pawn move.
-
 
1131
 
-
 
1132
bool Position::has_repeated() const {
-
 
1133
 
-
 
1134
    StateInfo* stc = st;
-
 
1135
    while (true)
-
 
1136
    {
-
 
1137
        int i = 4, end = std::min(stc->rule50, stc->pliesFromNull);
-
 
1138
 
-
 
1139
        if (end < i)
-
 
1140
            return false;
-
 
1141
 
-
 
1142
        StateInfo* stp = stc->previous->previous;
-
 
1143
 
-
 
1144
        do {
-
 
1145
            stp = stp->previous->previous;
-
 
1146
 
-
 
1147
            if (stp->key == stc->key)
-
 
1148
                return true;
-
 
1149
 
-
 
1150
            i += 2;
-
 
1151
        } while (i <= end);
-
 
1152
 
-
 
1153
        stc = stc->previous;
-
 
1154
    }
-
 
1155
}
-
 
1156
 
-
 
1157
 
-
 
1158
/// Position::has_game_cycle() tests if the position has a move which draws by repetition,
-
 
1159
/// or an earlier position has a move that directly reaches the current position.
-
 
1160
 
-
 
1161
bool Position::has_game_cycle(int ply) const {
-
 
1162
 
-
 
1163
  int j;
-
 
1164
 
-
 
1165
  int end = std::min(st->rule50, st->pliesFromNull);
-
 
1166
 
-
 
1167
  if (end < 3)
-
 
1168
    return false;
-
 
1169
 
-
 
1170
  Key originalKey = st->key;
-
 
1171
  StateInfo* stp = st->previous;
-
 
1172
 
-
 
1173
  for (int i = 3; i <= end; i += 2)
-
 
1174
  {
-
 
1175
      stp = stp->previous->previous;
-
 
1176
 
-
 
1177
      Key moveKey = originalKey ^ stp->key;
-
 
1178
      if (   (j = H1(moveKey), cuckoo[j] == moveKey)
-
 
1179
          || (j = H2(moveKey), cuckoo[j] == moveKey))
-
 
1180
      {
-
 
1181
          Move move = cuckooMove[j];
-
 
1182
          Square s1 = from_sq(move);
-
 
1183
          Square s2 = to_sq(move);
-
 
1184
 
-
 
1185
          if (!(between_bb(s1, s2) & pieces()))
-
 
1186
          {
-
 
1187
              // In the cuckoo table, both moves Rc1c5 and Rc5c1 are stored in the same
-
 
1188
              // location. We select the legal one by reversing the move variable if necessary.
-
 
1189
              if (empty(s1))
-
 
1190
                  move = make_move(s2, s1);
-
 
1191
 
-
 
1192
              if (ply > i)
-
 
1193
                  return true;
-
 
1194
 
-
 
1195
              // For repetitions before or at the root, require one more
-
 
1196
              StateInfo* next_stp = stp;
-
 
1197
              for (int k = i + 2; k <= end; k += 2)
-
 
1198
              {
-
 
1199
                  next_stp = next_stp->previous->previous;
-
 
1200
                  if (next_stp->key == stp->key)
-
 
1201
                     return true;
-
 
1202
              }
-
 
1203
          }
-
 
1204
      }
-
 
1205
  }
1106
  return false;
1206
  return false;
1107
}
1207
}
1108
 
1208
 
1109
 
1209
 
1110
/// Position::flip() flips position with the white and black sides reversed. This
1210
/// Position::flip() flips position with the white and black sides reversed. This
Line 1146... Line 1246...
1146
/// position object and raises an asserts if something wrong is detected.
1246
/// position object and raises an asserts if something wrong is detected.
1147
/// This is meant to be helpful when debugging.
1247
/// This is meant to be helpful when debugging.
1148
 
1248
 
1149
bool Position::pos_is_ok() const {
1249
bool Position::pos_is_ok() const {
1150
 
1250
 
1151
  const bool Fast = true; // Quick (default) or full check?
1251
  constexpr bool Fast = true; // Quick (default) or full check?
1152
 
1252
 
1153
  if (   (sideToMove != WHITE && sideToMove != BLACK)
1253
  if (   (sideToMove != WHITE && sideToMove != BLACK)
1154
      || piece_on(square<KING>(WHITE)) != W_KING
1254
      || piece_on(square<KING>(WHITE)) != W_KING
1155
      || piece_on(square<KING>(BLACK)) != B_KING
1255
      || piece_on(square<KING>(BLACK)) != B_KING
1156
      || (   ep_square() != SQ_NONE
1256
      || (   ep_square() != SQ_NONE