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