25 static uint hashVal [16][64];
    26 static uint stdStartHash = 0;
    27 static uint stdStartPawnHash = 0;
    30 #define HASH(h,p,sq)    (h) ^= hashVal[(p)][(sq)]    31 #define UNHASH(h,p,sq)  (h) ^= hashVal[(p)][(sq)]    38         HASH (PawnHash, p, sq);
    80 static void initHashValues (
void)
    83     static int firstCall = 1;
    84     if (! firstCall) { 
return; }
    90     for (
uint p = 0; p < 16; p++) {
    91         for (sq = 
A1; sq <= 
H8; sq++) { hashVal[p][
sq] = 0; }
    97     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WK][
sq] = *hash; hash++; }
    98     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WQ][
sq] = *hash; hash++; }
    99     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WR][
sq] = *hash; hash++; }
   100     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WB][
sq] = *hash; hash++; }
   101     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WN][
sq] = *hash; hash++; }
   102     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
WP][
sq] = *hash; hash++; }
   103     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BK][
sq] = *hash; hash++; }
   104     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BQ][
sq] = *hash; hash++; }
   105     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BR][
sq] = *hash; hash++; }
   106     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BB][
sq] = *hash; hash++; }
   107     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BN][
sq] = *hash; hash++; }
   108     for (sq=
A1; sq <= 
H8; sq++) { hashVal[
BP][
sq] = *hash; hash++; }
   117     stdStartPawnHash = h;
   140         for (i=
A1; i <= 
NS; i++) {
   141             for (j=
A1; j <= 
NS; j++) {
   146         for (i=
A1; i <= 
H8; i++) {
   148             while (*dirptr != NULL_DIR) {
   151                     sqDir[i][j] = *dirptr;
   201                 if (ptype == 
QUEEN  ||  ptype == attacker) {
   202                     Pinned[ListPos[friendly]] = dir;
   223     mlist->
emplace_back(from, to, promo, Board[from], Board[to]);
   240     while (dest != last) {
   244             if (! capturesOnly) {
   245                 if (sqset == NULL  ||  sqset->
Contains(dest)) {
   246                     AddLegalMove (mlist, fromSq, dest, 
EMPTY);
   253             if (sqset == NULL  ||  sqset->
Contains(dest)) {
   254                 AddLegalMove (mlist, fromSq, dest, 
EMPTY);
   275         if (capturesOnly  &&  p == 
EMPTY) { 
continue; }
   277             if (sqset == NULL  ||  sqset->
Contains(dest)) {
   278                 AddLegalMove (mlist, fromSq, dest, 
EMPTY);
   291 Position::GenCastling (
MoveList * mlist)
   295     if (from != (ToMove == 
WHITE ? 
E1 : 
E8))  { 
return; }
   304         if (ToMove == 
WHITE) {
   305             target = 
G1; skip = 
F1; rookSq = 
H1; rookPiece = 
WR;
   307             target = 
G8; skip = 
F8; rookSq = 
H8; rookPiece = 
BR;
   309         if (Board[target] == 
EMPTY  &&  Board[skip] == 
EMPTY   310                 &&  Board[rookSq] == rookPiece
   314             AddLegalMove (mlist, from, target, 
EMPTY);
   320         if (ToMove == 
WHITE) {
   321             target = 
C1; skip = 
D1; rookSq = 
A1; rookPiece = 
WR;
   323             target = 
C8; skip = 
D8; rookSq = 
A8; rookPiece = 
BR;
   325         if (Board[target] == 
EMPTY  &&  Board[skip] == 
EMPTY   326                 &&  Board[rookSq] == rookPiece
   327                 &&  Board[target - 1] == 
EMPTY    331             AddLegalMove (mlist, from, target, 
EMPTY);
   351     ASSERT (Board[kingSq] == king);
   358         bool addThisMove = 
false;
   362         if ( (genNonCaptures  &&  Board[destSq] == 
EMPTY)
   366             pieceT captured = Board[destSq];
   367             Board[destSq] = king;
   368             Board[kingSq] = 
EMPTY;
   377             Board[kingSq] = king;
   378             Board[destSq] = captured;
   380         if (addThisMove) { AddLegalMove (mlist, kingSq, destSq, 
EMPTY); }
   384     if (genNonCaptures  &&  castling) { GenCastling (mlist); }
   398     AddLegalMove (mlist, from, dest, 
QUEEN);
   399     AddLegalMove (mlist, from, dest, 
ROOK);
   400     AddLegalMove (mlist, from, dest, 
BISHOP);
   401     AddLegalMove (mlist, from, dest, 
KNIGHT);
   420     squareT enemyPawnSq = (ToMove == 
WHITE) ? to - 8 : to + 8;
   421     ASSERT (Board[from] == ownPawn);
   422     ASSERT (Board[enemyPawnSq] == enemyPawn);
   428     Board[enemyPawnSq] = 
EMPTY;
   434     Board[from] = ownPawn;
   435     Board[enemyPawnSq] = enemyPawn;
   454     if (ToMove == 
WHITE) {
   464           &&  (dir == 
NULL_DIR  ||  dir == forward  ||  oppdir == forward)) {
   466         if (Board[dest]==
EMPTY && (sqset==NULL || sqset->
Contains(dest))) {
   468                 AddPromotions (mlist, from, dest);
   470                 AddLegalMove (mlist, from, dest, 
EMPTY);
   475             if (Board[dest]==
EMPTY  &&  (sqset==NULL || sqset->
Contains(dest))) {
   476                 AddLegalMove (mlist, from, dest, 
EMPTY);
   484 #define POSSIBLE_CAPTURE(d) ((d != NULL_SQUARE)   \   485             &&  ((piece_Color (Board[d]) == (color_Flip(ToMove)))  \   486                     ||  (d == EPTarget  &&  IsValidEnPassant(from,d))))   489     if (dir == 
NULL_DIR  ||  dir == capdir  ||  oppdir == capdir) {
   493                 AddPromotions (mlist, from, dest);
   495                 AddLegalMove (mlist, from, dest, 
EMPTY);
   499     capdir = forward | 
RIGHT;
   500     if (dir == 
NULL_DIR  ||  dir == capdir  ||  oppdir == capdir) {
   504                 AddPromotions (mlist, from, dest);
   506                 AddLegalMove (mlist, from, dest, 
EMPTY);
   527     if (*b == 
WP) { hpSig |= 0x8000; }  b++;  
   528     if (*b == 
WP) { hpSig |= 0x4000; }  b++;  
   529     if (*b == 
WP) { hpSig |= 0x2000; }  b++;  
   530     if (*b == 
WP) { hpSig |= 0x1000; }  b++;  
   531     if (*b == 
WP) { hpSig |= 0x0800; }  b++;  
   532     if (*b == 
WP) { hpSig |= 0x0400; }  b++;  
   533     if (*b == 
WP) { hpSig |= 0x0200; }  b++;  
   534     if (*b == 
WP) { hpSig |= 0x0100; }        
   536     if (*b == 
BP) { hpSig |= 0x0080; }  b++;  
   537     if (*b == 
BP) { hpSig |= 0x0040; }  b++;  
   538     if (*b == 
BP) { hpSig |= 0x0020; }  b++;  
   539     if (*b == 
BP) { hpSig |= 0x0010; }  b++;  
   540     if (*b == 
BP) { hpSig |= 0x0008; }  b++;  
   541     if (*b == 
BP) { hpSig |= 0x0004; }  b++;  
   542     if (*b == 
BP) { hpSig |= 0x0002; }  b++;  
   543     if (*b == 
BP) { hpSig |= 0x0001; }        
   566     for (i=
A1; i <= 
H8; i++) { Board[i] = 
EMPTY; }
   567     for (i=
WK; i <= 
BP; i++) {
   569         for (
uint j=0; j < 8; j++) {
   570             NumOnRank[i][j] = NumOnFyle[i][j] = 0;
   572         for (
uint d=0; d < 15; d++) {
   573             NumOnLeftDiag[i][d] = NumOnRightDiag[i][d] = 0;
   575         NumOnSquareColor[i][
WHITE] = NumOnSquareColor[i][
BLACK] = 0;
   596     static Position startPositionTemplate;
   597     static bool init = 
true;
   601         Position* p = &startPositionTemplate;
   603         p->Material[
WK] = p->Material[
BK] = 1;
   604         p->Material[
WQ] = p->Material[
BQ] = 1;
   605         p->Material[
WR] = p->Material[
BR] = 2;
   606         p->Material[
WB] = p->Material[
BB] = 2;
   607         p->Material[
WN] = p->Material[
BN] = 2;
   608         p->Material[
WP] = p->Material[
BP] = 8;
   611         p->AddToBoard(
WK, 
E1);  p->List[
WHITE][0] = 
E1;  p->ListPos[
E1] = 0;
   612         p->AddToBoard(
BK, 
E8);  p->List[
BLACK][0] = 
E8;  p->ListPos[
E8] = 0;
   613         p->AddToBoard(
WR, 
A1);  p->List[
WHITE][1] = 
A1;  p->ListPos[
A1] = 1;
   614         p->AddToBoard(
BR, 
A8);  p->List[
BLACK][1] = 
A8;  p->ListPos[
A8] = 1;
   615         p->AddToBoard(
WN, 
B1);  p->List[
WHITE][2] = 
B1;  p->ListPos[
B1] = 2;
   616         p->AddToBoard(
BN, 
B8);  p->List[
BLACK][2] = 
B8;  p->ListPos[
B8] = 2;
   617         p->AddToBoard(
WB, 
C1);  p->List[
WHITE][3] = 
C1;  p->ListPos[
C1] = 3;
   618         p->AddToBoard(
BB, 
C8);  p->List[
BLACK][3] = 
C8;  p->ListPos[
C8] = 3;
   619         p->AddToBoard(
WQ, 
D1);  p->List[
WHITE][4] = 
D1;  p->ListPos[
D1] = 4;
   620         p->AddToBoard(
BQ, 
D8);  p->List[
BLACK][4] = 
D8;  p->ListPos[
D8] = 4;
   621         p->AddToBoard(
WB, 
F1);  p->List[
WHITE][5] = 
F1;  p->ListPos[
F1] = 5;
   622         p->AddToBoard(
BB, 
F8);  p->List[
BLACK][5] = 
F8;  p->ListPos[
F8] = 5;
   623         p->AddToBoard(
WN, 
G1);  p->List[
WHITE][6] = 
G1;  p->ListPos[
G1] = 6;
   624         p->AddToBoard(
BN, 
G8);  p->List[
BLACK][6] = 
G8;  p->ListPos[
G8] = 6;
   625         p->AddToBoard(
WR, 
H1);  p->List[
WHITE][7] = 
H1;  p->ListPos[
H1] = 7;
   626         p->AddToBoard(
BR, 
H8);  p->List[
BLACK][7] = 
H8;  p->ListPos[
H8] = 7;
   628         for (
uint i=0; i < 8; i++) {
   629             p->AddToBoard(
WP, 
A2+i); p->List[
WHITE][i+8] = 
A2+i; p->ListPos[
A2+i] = i+8;
   630             p->AddToBoard(
BP, 
A7+i); p->List[
BLACK][i+8] = 
A7+i; p->ListPos[
A7+i] = i+8;
   639         p->HalfMoveClock = 0;
   641         p->Hash = stdStartHash;
   642         p->PawnHash = stdStartPawnHash;
   644     return startPositionTemplate;
   652           ||  Hash != stdStartHash  ||  PawnHash != stdStartPawnHash
   674     if ((c != 
WHITE && c != 
BLACK) || Count[c] > 15)
   685             List[c][Count[c]] = oldsq;
   686             ListPos[oldsq] = Count[c];
   691         ListPos[
sq] = Count[c];
   692         List[c][Count[c]] = 
sq;
   713     Pinned[ 0] = Pinned[ 1] = Pinned[ 2] = Pinned[ 3] = Pinned[ 4] =
   714     Pinned[ 5] = Pinned[ 6] = Pinned[ 7] = Pinned[ 8] = Pinned[ 9] =
   715     Pinned[10] = Pinned[11] = Pinned[12] = Pinned[13] = Pinned[14] =
   761         GenKnightMoves (mlist, c, fromSq, sqset, capturesOnly);
   765         GenSliderMoves (mlist, c, fromSq, 
UP, sqset, capturesOnly);
   766         GenSliderMoves (mlist, c, fromSq, 
DOWN, sqset, capturesOnly);
   767         GenSliderMoves (mlist, c, fromSq, 
LEFT, sqset, capturesOnly);
   768         GenSliderMoves (mlist, c, fromSq, 
RIGHT, sqset, capturesOnly);
   771         GenSliderMoves (mlist, c, fromSq, 
UP_LEFT, sqset, capturesOnly);
   772         GenSliderMoves (mlist, c, fromSq, 
DOWN_LEFT, sqset, capturesOnly);
   773         GenSliderMoves (mlist, c, fromSq, 
UP_RIGHT, sqset, capturesOnly);
   774         GenSliderMoves (mlist, c, fromSq, 
DOWN_RIGHT, sqset, capturesOnly);
   790     bool capturesOnly = !genNonCaptures;
   793     if (pieceType != 
EMPTY) {
   794         mask = 1 << pieceType;
   816             GenCheckEvasions (mlist, pieceType, genType, &checkSquares);
   824     uint npieces = Count[ToMove];
   825     for (
uint x = 1; x < npieces; x++) {
   829         if (! (mask & (1 << ptype))) { 
continue; }
   837                 GenPawnMoves (mlist, sq, pinned, NULL, genType);
   838             } 
else if (ptype == 
KNIGHT) {
   846                     GenSliderMoves (mlist, ToMove, sq, pinned, NULL, capturesOnly);
   847                     GenSliderMoves (mlist, ToMove, sq, 
dirOpposite[pinned],
   854                 GenPawnMoves (mlist, sq, 
NULL_DIR, NULL, genType);
   863     if (mask & (1 << 
KING)) {
   864         bool castling = !numChecks;
   865         GenKingMoves (mlist, genType, castling);
   877     if (from > 
H8  ||  to > 
H8) { 
return false; }
   878     if (from == to) { 
return false; }
   879     pieceT mover = Board[from];
   880     pieceT captured = Board[to];
   881     if (
piece_Color(mover) != ToMove) { 
return false; }
   882     if (
piece_Color(captured) == ToMove) { 
return false; }
   891         int rdiff = (int)rto - (
int)rfrom;
   893         if (rdiff < 1  ||  rdiff > 2) { 
return false; }
   894         if (fdiff < -1  ||  fdiff > 1) { 
return false; }
   896             if (captured != 
EMPTY) { 
return false; }
   898                 if (rfrom != 
RANK_2) { 
return false; }
   900                 squareT midsquare = from + ((to - from) / 2);
   901                 if (Board[midsquare] != 
EMPTY) { 
return false; }
   904             if (rdiff != 1) { 
return false; }
   905             if (captured == 
EMPTY) {
   907                 if (to != EPTarget) { 
return false; }
   923         if (dir == 
NULL_DIR) { 
return false; }
   930             if (Board[dest] != 
EMPTY) { 
return false; }
   934     } 
else if (mover == 
KNIGHT) {
   944             GenCastling (&mlist);
   955     return (nchecks == 0);
   967     pieceT promote2 = promote;
   983     if (ToMove == 
WHITE) {
   987         if (toRank == 
RANK_4  &&  fromFyle == toFyle) { backup = to - 16; }
   992         if (toRank == 
RANK_5  &&  fromFyle == toFyle) { backup = to + 16; }
   997     if (toRank == promoteRank) {
   999         if (promote == 
EMPTY)  {
  1007     if (Board[from] != pawn) {
  1009         if (backup == 
NS || Board[from] != 
EMPTY || Board[backup] != pawn) {
  1020     if (fromFyle == toFyle) {
  1024         Board[to] = pawn;  Board[from] = 
EMPTY;
  1028        Board[to] = 
EMPTY; Board[from] = pawn;
  1033         pieceT captured = Board[to];
  1034         if (captured == 
EMPTY) {
  1041             ASSERT (Board[epSquare] == enemyPawn);
  1043             Board[to] = pawn; Board[from] = 
EMPTY;
  1044             Board[epSquare] = 
EMPTY;
  1045             Material[enemyPawn] --;
  1047             Board[epSquare] = enemyPawn;
  1050             Material[enemyPawn]++;
  1058                 Board[to] = pawn;  Board[from] = 
EMPTY;
  1059                 Material[captured]--;
  1063                 Material[captured]++;
  1064                 Board[to] = captured; Board[from] = pawn;
  1070         AddLegalMove (mlist, from, to, promote2);
  1086     uint numChecks = checkSquares->
Size();
  1092     bool capturesOnly = !genNonCaptures;
  1098     if (numChecks == 1) {
  1107         targets.
Add(attackSq);
  1112             while (sq != attackSq) {
  1113                 if (Board[sq] == 
EMPTY) { targets.
Add(sq); }
  1122         uint numPieces = Count[ToMove];
  1123         for (
uint p2 = 1; p2 < numPieces; p2++) {
  1124             squareT from = List[ToMove][p2];
  1125             pieceT p2piece = Board[from];
  1126             if (Pinned[p2] != 
NULL_DIR) { 
continue; }
  1129                     GenPawnMoves (mlist, from, 
NULL_DIR, &targets, genType);
  1136                         squareT pawnSq = (ToMove == 
WHITE ? EPTarget - 8 : EPTarget + 8);
  1137                         if (pawnSq == attackSq) {
  1139                             epset.
Add(EPTarget);
  1140                             GenPawnMoves (mlist, from, 
NULL_DIR, &epset, genType);
  1151     if (mask == 
EMPTY  ||  mask == 
KING) { GenKingMoves(mlist, genType, 
false); }
  1164   uint moveCount = 0, zeroCount = 0;
  1167   for (
uint i=0; i < moveList.
Size(); i++) {
  1169     if (smPtr->
to == target) {
  1175       if (!score && ++zeroCount > 1) 
return -2;
  1176       if (score > maxScore) maxScore = score;
  1180  if (!moveCount) 
return 0;
  1181  if (!maxScore) 
return -1;
  1205     if (fromSquares == NULL) { fromSquares = &fromSqs; }
  1207     fromSquares->
Clear();
  1211     pieceT king, queen, rook, bishop, knight;
  1212     if (side == 
WHITE) {
  1213         king = 
WK; queen = 
WQ; rook = 
WR; bishop = 
WB; knight = 
WN;
  1215         king = 
BK; queen = 
BQ; rook = 
BR; bishop = 
BB; knight = 
BN;
  1218     uint numQueensRooks = Material[queen] + Material[rook];
  1219     uint numQueensBishops = Material[queen] + Material[bishop];
  1222     if (numQueensRooks > 0) {
  1228             dirs[ndirs++] = 
UP;  dirs[ndirs++] = 
DOWN;
  1231             dirs[ndirs++] = 
LEFT; dirs[ndirs++] = 
RIGHT;
  1233         for (
uint i = 0; i < ndirs; i++) {
  1239             while (dest != last) {
  1244                 } 
else if (p == queen  ||  p == rook) {
  1246                     fromSquares->
Add(dest);
  1257     if (numQueensBishops > 0) {
  1268         for (
uint i = 0; i < ndirs; i++) {
  1274             while (dest != last) {
  1279                 } 
else if (p == queen  ||  p == bishop) {
  1281                     fromSquares->
Add(dest);
  1293     if (Material[knight] > 0
  1299             if (Board[dest] == knight) {
  1300                 fromSquares->
Add(dest);
  1307     if (side == 
WHITE) {
  1310             if (Board[sq] == 
WP)  {
  1311                 fromSquares->
Add(sq);
  1314             if (Board[sq] == 
WP)  {
  1315                 fromSquares->
Add(sq);
  1321             if (Board[sq] == 
BP)  {
  1322                 fromSquares->
Add(sq);
  1325             if (Board[sq] == 
BP)  {
  1326                 fromSquares->
Add(sq);
  1333     do if (Board[*destPtr] == king) fromSquares->
Add(*destPtr);
  1336     return fromSquares->
Size();
  1356     if (nSliders == 0) { 
return false; }
  1383     if (nSliders == 0) { 
return false; }
  1390     while (dest != last) {
  1395         } 
else if (p == queen  ||  p == slider) {
  1439         if (ToMove == 
WHITE) {
  1440             if (Material[
BP] > 0) {
  1442                 if (Board[sq] == 
BP)  { 
return true; }
  1444                 if (Board[sq] == 
BP)  { 
return true; }
  1447             if (Material[
WP] > 0) {
  1449                 if (Board[sq] == 
WP)  { 
return true; }
  1451                 if (Board[sq] == 
WP)  { 
return true; }
  1454     } 
else if (p == 
KNIGHT) {
  1456     } 
else if (p == 
KING) {
  1486     for (
uint i=0; i < 4; i++) {
  1492         while (dest != last) {
  1517     if (numChecks == 0) { 
return false; }
  1521     if (mlist.
Size() == 0) { 
return true; }
  1557     rankT seventh, eighth;
  1564     if ( (fromR == seventh  &&  toR == eighth  &&  Board[from] == pawn)  ||
  1565          (toR == seventh  &&  fromR == eighth  &&  Board[to] == pawn) ) {
  1628         ListPos[List[enemy][Count[enemy]]] = sm->
capturedNum;
  1629         List[enemy][sm->
capturedNum] = List[enemy][Count[enemy]];
  1640         RemoveFromBoard (p, from);
  1643         AddToBoard (p, from);
  1649     RemoveFromBoard (p, from);
  1665         ListPos[rookto] = ListPos[rookfrom];
  1666         List[ToMove][ListPos[rookto]] = rookto;
  1667         RemoveFromBoard (rook, rookfrom);
  1668         AddToBoard (rook, rookto);
  1674         if (ptype == 
KING) {   
  1679         if (ToMove == 
WHITE) {
  1695     if (ptype == 
PAWN) {
  1759         RemoveFromBoard (p, to);
  1769     RemoveFromBoard (p, to);
  1770     AddToBoard (p, from);
  1782             rookfrom = to - 2;   rookto = to + 1;
  1784             rookfrom = to + 1;   rookto = to - 1;
  1786         ListPos[rookfrom] = ListPos[rookto];
  1787         List[ToMove][ListPos[rookto]] = rookfrom;
  1788         RemoveFromBoard (rook, rookto);
  1789         AddToBoard (rook, rookfrom);
  1808     if (fromSq == 
NS ||  toSq == 
NS) { 
return ERROR; }
  1811     if (fromSq == toSq) { 
return OK; }
  1821     if (ptype == 
PAWN) {
  1827     uint index = ListPos[fromSq];
  1828     ASSERT(List[pcolor][index] == fromSq);
  1831     List[pcolor][index] = toSq;
  1832     ListPos[toSq] = index;
  1833     RemoveFromBoard (piece, fromSq);
  1834     AddToBoard (piece, toSq);
  1839         List[pcolor][index] = fromSq;
  1840         RemoveFromBoard (piece, toSq);
  1841         AddToBoard (piece, fromSq);
  1890     ASSERT (m != NULL  &&  s != NULL);
  1913     } 
else if (p == 
KING) {
  1916             *c++ = 
'-'; *c++ = 
'-';
  1921                 if (Board[to] != 
EMPTY)
  1946         if (Material[piece] > 1) {
  1948             for (
uint i = 1, n = Count[ToMove]; i < n; i++) {
  1950                 if (sq == from || Board[sq] != piece)
  1956                 std::pair<pieceT, squareT> pin =
  1961                     if (pt == 
QUEEN || pt == pin.first)
  1984         if (Board[to] != 
EMPTY)
  1993         Board[to] = Board[from];
  1994         Board[from] = 
EMPTY;
  1996         check = (p != 
KING) &&
  1999             bool enpassant = (p == 
PAWN && oldTo == 
EMPTY &&
  2011         Board[from] = Board[to];
  2024                 if (mlist.
Size() == 0) { ch = 
'#'; }
  2040     ASSERT (m != NULL  &&  s != NULL);
  2083     ASSERT (m != NULL  &&  str != NULL);
  2084     fyleT fromFyle, toFyle;
  2085     rankT fromRank, toRank;
  2105     for (
size_t i = 0, n = mlist.
Size(); i < n; i++) {
  2108             if (sm->
from == from  &&  sm->
to == to) {
  2112             if (reverse  &&  sm->
to == from  &&  sm->
from == to) {
  2121 static int trimCheck(
const char* str, 
int slen) {
  2124         if (str[slen] != 
'#' && str[slen] != 
'+') {
  2136     slen = trimCheck(str, slen);
  2140     auto is_digit = [](
char ch) {
  2141         return isdigit(static_cast<unsigned char>(ch));
  2143     auto is_lower = [](
char ch) {
  2144         return islower(static_cast<unsigned char>(ch));
  2148         is_digit(str[1]) && is_lower(str[2]) && is_digit(str[3])) {
  2154     auto last_ch = 
static_cast<unsigned char>(str[slen - 1]);
  2155     if (!is_digit(last_ch)) {
  2164         if (str[slen - 1] == 
'=') {
  2173     if (slen == 2 && (str[1] >= 
'a' && str[1] <= 
'h')) {
  2178             if (MatchPawnMove(&mlist, frFyle, to, promo) == 
OK) {
  2179                 *sm = *(mlist.
Get(0));
  2193     if (MatchPawnMove(&mlist, frFyle, to, promo) != 
OK)
  2196     *sm = *(mlist.
Get(0));
  2201     ASSERT(sm != NULL && str != NULL);
  2203     slen = trimCheck(str, slen);
  2204     if (slen < 3 || slen > 6)
  2217     pieceT captured = Board[target];
  2230     Board[target] = movingPiece;
  2231     Board[kingSq] = 
EMPTY;
  2232     if (captured != 
EMPTY) {
  2233         Material[captured]--;
  2236     if (captured != 
EMPTY) {
  2237         Material[captured]++;
  2239     Board[target] = captured;
  2240     Board[kingSq] = movingPiece;
  2259     ASSERT(sm != NULL && str != NULL);
  2263     slen = trimCheck(str, slen);
  2264     if (slen < 3 || slen > 6)
  2273     pieceT captured = Board[to];
  2284         if (frRank == 
NO_RANK && slen > 4) {
  2292     auto movingPiece = 
piece_Make(ToMove, piece);
  2293     int nPieces = Material[movingPiece];
  2295     for (
unsigned i = 1, n = Count[ToMove]; i < n && nPieces; i++) {
  2296         auto from = List[ToMove][i];
  2297         if (Board[from] != movingPiece)
  2310             auto p = Board[pin.second];
  2322     return (matchCount == 1) ? 
OK                   2328     slen = trimCheck(str, slen);
  2330     auto str_equal = [&](
const char* const_str, 
const int len) {
  2331         return slen == len && std::equal(str, str + len, const_str);
  2335     if (str_equal(
"O-O", 3) || str_equal(
"OO", 2)) {
  2337         if (kingSq != (ToMove == 
WHITE ? 
E1 : 
E8))
  2340         if (Board[kingSq + 1] != 
EMPTY || Board[kingSq + 2] != 
EMPTY ||
  2346         sm->
to = kingSq + 2;
  2353     if (str_equal(
"O-O-O", 5) || str_equal(
"OOO", 3)) {
  2355         if (kingSq != (ToMove == 
WHITE ? 
E1 : 
E8))
  2358         if (Board[kingSq - 1] != 
EMPTY || Board[kingSq - 2] != 
EMPTY ||
  2364         sm->
to = kingSq - 2;
  2374     while (!isalpha(static_cast<unsigned char>(*str)) && *str != 
'\0') {
  2377     const char* begin = str;
  2378     while (!isspace(static_cast<unsigned char>(*str)) && *str != 
'\0') {
  2389                            const char* strEnd) {
  2392     int length = 
static_cast<int>(std::distance(str, strEnd));
  2393     if (length < 2 || length > 9)
  2398         return ReadMovePawn(sm, str, length, 
A_FYLE);
  2400         return ReadMovePawn(sm, str, length, 
B_FYLE);
  2402         return ReadMovePawn(sm, str, length, 
C_FYLE);
  2404         return ReadMovePawn(sm, str, length, 
D_FYLE);
  2406         return ReadMovePawn(sm, str, length, 
E_FYLE);
  2408         return ReadMovePawn(sm, str, length, 
F_FYLE);
  2410         return ReadMovePawn(sm, str, length, 
G_FYLE);
  2412         return ReadMovePawn(sm, str, length, 
H_FYLE);
  2414         return ReadMoveKing(sm, str, length);
  2416         return ReadMove(sm, str, length, 
QUEEN);
  2418         return ReadMove(sm, str, length, 
ROOK);
  2420         return ReadMove(sm, str, length, 
BISHOP);
  2422         return ReadMove(sm, str, length, 
KNIGHT);
  2424         return ReadMoveCastle(sm, str, length);
  2428     if ((length == 2 && std::equal(str, str + 2, 
"--")) ||
  2429         (length == 2 && std::equal(str, str + 2, 
"Z0")) ||
  2430         (length == 4 && std::equal(str, str + 4, 
"null"))) {
  2442         return ReadMovePawn(sm, str, length, 
A_FYLE);
  2444         return ReadMovePawn(sm, str, length, 
C_FYLE);
  2446         return ReadMovePawn(sm, str, length, 
D_FYLE);
  2448         return ReadMovePawn(sm, str, length, 
E_FYLE);
  2450         return ReadMovePawn(sm, str, length, 
F_FYLE);
  2452         return ReadMovePawn(sm, str, length, 
G_FYLE);
  2454         return ReadMovePawn(sm, str, length, 
H_FYLE);
  2458         return ReadMoveKing(sm, str, length);
  2460         return ReadMove(sm, str, length, 
QUEEN);
  2462         return ReadMove(sm, str, length, 
ROOK);
  2464         return ReadMove(sm, str, length, 
KNIGHT);
  2478     for (
size_t i = 0, n = mlist.
Size(); i < n; i++) {
  2489     pieceFromByte [(int) 
'K'] = 
WK;  pieceFromByte [(int) 
'k'] = 
BK;
  2490     pieceFromByte [(int) 
'Q'] = 
WQ;  pieceFromByte [(int) 
'q'] = 
BQ;
  2491     pieceFromByte [(int) 
'R'] = 
WR;  pieceFromByte [(int) 
'r'] = 
BR;
  2492     pieceFromByte [(int) 
'B'] = 
WB;  pieceFromByte [(int) 
'b'] = 
BB;
  2493     pieceFromByte [(int) 
'N'] = 
WN;  pieceFromByte [(int) 
'n'] = 
BN;
  2494     pieceFromByte [(int) 
'P'] = 
WP;  pieceFromByte [(int) 
'p'] = 
BP;
  2498         if (str[
sq] == 
'.') { 
continue; }
  2534     *s++ = (ToMove == 
WHITE ? 
'w' : 
'b');
  2553     for (
uint i=0; i < 32; i++) {
  2567     colorT toMove = str[32] - 1;
  2572     Castling = str[33] - 1;
  2573     EPTarget = str[34] - 1;
  2580     for (
uint i=0; i < 32; i++) {
  2582         cboard[i] = (
byte)(Board[i2] << 4) | Board[i2+1];
  2584     cboard[32] = 1 + ToMove;
  2585     cboard[33] = 1 + Castling;
  2593     if (ToMove == 
WHITE) {
  2602     cboard[34] = 1 + ep;
  2609     for (
uint i=0; i < 32; i++) {
  2612         i2 = ((7 - (i2)/8) * 8 + ((i2) % 8));
  2617     cboard[33] = 1 + Castling;
  2618     cboard[34] = 1 + EPTarget;
  2640     auto is_space = [](
char ch) {
  2641         return isspace(static_cast<unsigned char>(ch));
  2645     static pieceT pieceFromByte [256];
  2649     static squareT fenSqToRealSquare [64];
  2652     static int firstCall = 1;
  2655     const char * s = str;
  2662         for (
int i=0; i < 256; i++) { pieceFromByte[i] = 
EMPTY; }
  2663         pieceFromByte [(int) 
'K'] = 
WK;  pieceFromByte [(int) 
'k'] = 
BK;
  2664         pieceFromByte [(int) 
'Q'] = 
WQ;  pieceFromByte [(int) 
'q'] = 
BQ;
  2665         pieceFromByte [(int) 
'R'] = 
WR;  pieceFromByte [(int) 
'r'] = 
BR;
  2666         pieceFromByte [(int) 
'B'] = 
WB;  pieceFromByte [(int) 
'b'] = 
BB;
  2667         pieceFromByte [(int) 
'N'] = 
WN;  pieceFromByte [(int) 
'n'] = 
BN;
  2668         pieceFromByte [(int) 
'P'] = 
WP;  pieceFromByte [(int) 
'p'] = 
BP;
  2671         for (
int sq=0; 
sq < 64; 
sq++) {
  2672             fenSqToRealSquare [
sq] = (
squareT)((7 - (
sq)/8) * 8 + ((
sq) % 8));
  2677     while (count < 64) {
  2684         } 
else if (*s > 
'0'  &&  *s < 
'9') {
  2685             count += (*s - 
'0');
  2690             if (
AddPiece (p, fenSqToRealSquare[count]) != 
OK) {
  2700     while (is_space(*s)) { s++; }
  2716     while (is_space(*s)) { s++; }
  2719     } 
else if (*s == 0) {
  2723         if (Board[
E1] == 
WK) {
  2727         if (Board[
E8] == 
BK) {
  2732         while (!is_space(*s)  &&  *s != 0) {
  2754     while (is_space(*s)) { s++; }
  2757     } 
else if (*s == 
'-') {
  2761         char fylec = *s; s++;
  2762         if (fylec < 'a'  ||  fylec > 
'h') {
  2765         char rankc = *s; s++;
  2766         if (rankc != 
'3'  &&  rankc != 
'6') {
  2773     while (is_space(*s)) { s++; }
  2775         HalfMoveClock = (
ushort) atoi(s);
  2777     while (!is_space(*s)  && *s != 0) { s++; }
  2780     while (is_space(*s)) { s++; }
  2784             PlyCounter = (i - 1) * 2;
  2787     if (ToMove == 
BLACK) { PlyCounter++; }
  2806     uint emptyRun, iRank, iFyle;
  2807     for (iRank = 0; iRank < 8; iRank++) {
  2808         const pieceT* pBoard = &(Board[(7 - iRank) * 8]);
  2810         if (iRank > 0  &&  flags > 
FEN_COMPACT) { *str++ = 
'/'; }
  2811         for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) {
  2812             if (*pBoard != 
EMPTY) {
  2813                 if (emptyRun) { *str++ = (
byte) emptyRun + 
'0'; }
  2820         if (emptyRun) { *str++ = (
byte) emptyRun + 
'0'; }
  2824     *str++ = (ToMove == 
WHITE ? 
'w' : 
'b');
  2830         if (Castling == 0)  {
  2852             sprintf (str, 
"%d %d", HalfMoveClock, (PlyCounter / 2) + 1);
  2881     const uint HTML_DIAG_STYLES = 2;
  2885     if (style >= HTML_DIAG_STYLES) { style = 0; }
  2891     if (dir == NULL) { dir = hs[style].
dir; }
  2893     dstr->
Append (
"<br><br><center>\n");
  2894     dstr->
Append (
"<table Border=1 CellSpacing=0 CellPadding=0>\n");
  2895     for (iRank = 0; iRank < 8; iRank++) {
  2897         pBoard = &(Board[(7 - iRank) * 8]);
  2898         for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) {
  2900             if (flip) { piece = Board[iRank * 8 + (7 - iFyle)]; }
  2901             dstr->
Append (
"  <td><img border=0 ");
  2904                 sprintf (temp, 
"width=%u ", width);
  2909                 sprintf (temp, 
"height=%u ", height);
  2915             bool lightSq = ((iRank % 2) == (iFyle % 2));
  2921             if (piece == 
EMPTY) {
  2929             dstr->
Append (
"\" alt=\"");
  2930             if (piece == 
EMPTY) {
  2931                 if (! lightSq) { dstr->
Append (
"::"); }
  2937             dstr->
Append (
"\"></td>\n");
  2939         dstr->
Append (
"</tr>\n");
  2941     dstr->
Append (
"</table>\n");
  2947     dstr->
Append(
"</center><br>");
  2959     dstr->
Append (
"\\board{");
  2960     for (iRank = 0; iRank < 8; iRank++) {
  2961         pBoard = &(Board[(7 - iRank) * 8]);
  2962         for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) {
  2964             if (flip) { piece = Board[iRank * 8 + (7 - iFyle)]; }
  2965             if (piece != 
EMPTY) {
  2968                 dstr->
AddChar (((iRank % 2) == (iFyle % 2)) ? 
' ' : 
'*');
  2973         } 
else { dstr->
AddChar (
'}'); }
  2988     while (i   &&  *p1 == *p2) {
  2991     if (p1 < p2) { 
return -1; }
  2992     if (p1 > p2) { 
return 1; }
  3006     for (
uint i=0; i < npieces; i++) {
  3009         if (p == piece) { sqlist->
Add (sq); }
  3011     return Material[
piece];
  3028     uint nPieces[2] = {0, 0};   
  3039         char ch = toupper(*material);
  3040         if (ch == 0) { 
break; }
  3046         case 'Q':  
case 'R':  
case 'B':  
case 'N':  
case 'P':
  3056         case ' ':  
case '-':  
case '.':  
case ',':  
case ':':
  3079         for (
uint i=0; i < total; i++) {
  3085                 if (Board[sq] == 
EMPTY) { 
break; }
  3094         if (
CalcAttacks (ToMove, enemyKing, NULL) == 0) { 
break; }
 void GenerateCaptures(MoveList *mlist)
 
void DumpHtmlBoard(DString *dstr, uint style, const char *dir, bool flip)
 
errorT Random(const char *material)
 
fyleT fyle_FromChar(char c)
 
void PrintCompactStr(char *cboard)
 
pieceT piece_Type(pieceT p)
 
void MakeSANString(simpleMoveT *sm, char *s, sanFlagT flag)
 
bool square_IsKnightHop(squareT from, squareT to)
 
bool attack(squareT sqFrom, squareT sqTo, pieceT pieceCol, pieceT pieceType, const TBoard *board, const TBoard EMPTY_SQUARE)
Validate an ATTACK move, that is if a piece placed at sqFrom can capture an enemy piece at sqTo...
 
colorT square_Color(squareT sq)
 
simpleMoveT * Get(size_t index)
 
const squareT NULL_SQUARE
 
uint FyleCount(pieceT p, fyleT f) const
 
static const Position & getStdStart()
 
void init()
init() - initialize the pool of databases. 
 
constexpr squareT square_Move(squareT sq, directionT dir)
 
const directionT dirOpposite[11]
 
const squareT kingAttacks[66][9]
 
bool pseudo(squareT sqFrom, squareT sqTo, colorT, pieceT pieceType, const TBoard *board, const TBoard EMPTY_SQUARE)
 
void PrintCompactStrFlipped(char *cboard)
 
uint RightDiagCount(pieceT p, rightDiagT diag)
 
const errorT ERROR_CastlingAvailability
 
errorT AddPiece(pieceT p, squareT sq)
 
errorT ReadFromCompactStr(const byte *str)
 
errorT RelocatePiece(squareT fromSq, squareT toSq)
 
void DoSimpleMove(simpleMoveT *sm)
 
rankT square_Rank(squareT sq)
 
errorT ReadFromFEN(const char *s)
 
bool IsLegalMove(simpleMoveT *sm)
 
const squareT * GetList(colorT c) const
 
void MakeUCIString(simpleMoveT *sm, char *s)
 
colorT color_Flip(colorT c)
 
squareT randomPawnSquare(void)
 
uint CalcAttacks(colorT toMove, squareT kingSq, SquareList *squares)
 
bool piece_IsKing(pieceT p)
 
#define POSSIBLE_CAPTURE(d)
 
byte PieceCount(pieceT p)
 
const errorT ERROR_InvalidFEN
 
std::pair< pieceT, squareT > opens_ray(squareT sqFrom, squareT sqTo, squareT sqRay, const TBoard *board, const TBoard EMPTY_SQUARE)
Given a pseudo-legal move, this functions return the type and the location of the piece that can poss...
 
squareT square_Make(fyleT f, rankT r)
 
int find(const char *filename)
find() - search for a database. 
 
bool valid_king(squareT sqFrom, squareT sqTo)
 
uint GetSquares(pieceT p, SquareList *sqlist)
 
const pieceT PIECE_FLIP[MAX_PIECE_TYPES]
 
const directionT UP_RIGHT
 
void SetCastling(colorT c, castleDirT dir, bool flag)
 
const pieceT INVALID_PIECE
 
bool Contains(squareT sq)
 
void UndoSimpleMove(simpleMoveT *sm)
 
void CalcSANStrings(sanListT *sanList, sanFlagT flag)
 
void PrintFEN(char *str, uint flags) const
 
void GenPieceMoves(MoveList *mlist, squareT sq, SquareSet *sqset, bool capturesOnly)
 
int direction_Delta(directionT dir)
 
uint LeftDiagCount(pieceT p, leftDiagT diag)
 
rightDiagT square_RightDiag(squareT sq)
 
errorT ReadFromLongStr(const char *str)
 
rankT rank_FromChar(char c)
 
bool IsKingInCheckDir(directionT dir)
 
const errorT ERROR_InvalidMove
 
uint MaterialValue(colorT c)
 
bool attack_slider(squareT sqFrom, squareT sqTo, pieceT pieceType, const TBoard *board, const TBoard EMPTY_SQUARE)
 
void DumpLatexBoard(DString *dstr, bool flip)
 
errorT ParseMove(simpleMoveT *sm, const char *str)
 
errorT ReadCoordMove(simpleMoveT *m, const char *s, int slen, bool reverse)
 
bool IsPromoMove(squareT from, squareT to)
 
uint Mobility(pieceT p, colorT color, squareT from)
 
void GenerateMoves(MoveList *mlist, pieceT mask, genMovesT genType, bool maybeInCheck)
 
const directionT NULL_DIR
 
const sanFlagT SAN_NO_CHECKTEST
 
pieceT piece_FromChar(int x)
 
leftDiagT square_LeftDiag(squareT sq)
 
char square_FyleChar(squareT sq)
 
const genMovesT GEN_ALL_MOVES
 
colorT piece_Color(pieceT p)
 
const squareT knightAttacks[66][9]
 
directionT direction_Opposite(directionT d)
 
uint RankCount(pieceT p, rankT r) const
 
uint SquareColorCount(pieceT p, colorT sqColor)
 
void MakeLongStr(char *str)
 
struct sqDir_Init sqDir_Init_singleton
 
const pieceT END_OF_BOARD
 
const errorT ERROR_Corrupt
 
colorT piece_Color_NotEmpty(pieceT p)
 
bool direction_IsDiagonal(directionT dir)
 
const genMovesT GEN_NON_CAPS
 
constexpr squareT square_Last(squareT sq, directionT dir)
 
bool square_Adjacent(squareT from, squareT to)
 
const directionT DOWN_RIGHT
 
squareT GetEnemyKingSquare()
 
const squareT COLOR_SQUARE
 
const errorT ERROR_PieceCount
 
int TreeCalcAttacks(colorT toMove, squareT target)
 
Implements functions for the validation of chess moves. 
 
squareT randomSquare(void)
 
pieceT piece_Make(colorT c, pieceT p)
 
char square_RankChar(squareT sq)
 
sanStringT list[MAX_LEGAL_MOVES]
 
uint GetCount(colorT c) const
 
const uint FEN_CASTLING_EP
 
const directionT DOWN_LEFT
 
char piece_Char(pieceT p)
 
bool GetCastling(colorT c, castleDirT dir) const
 
const uint goodHashValues[12 *64]
 
void emplace_back(squareT from, squareT to, pieceT promote, pieceT movingPiece, pieceT capturedPiece)
 
const sanFlagT SAN_MATETEST
 
fyleT square_Fyle(squareT sq)
 
bool piece_IsSlider(pieceT p)
 
const uint FEN_ALL_FIELDS