34 "PPKRQDRTBFNC",
"PPKRQDRTBANC",
"PBKKQDRTBLNS",
35 "PPKRQDRTBANC",
"PpKKQDRTBLNP",
"PPKKQDRVBSNJ",
36 "PGKKQVRBBFNH",
"PBKKQDRTBLNS",
"PBKKQDRTBLNS",
"PPKRQDRTBANC",
"PSKKQDRTBLNR",
"" };
47 if (*ptr >=
'A' && *ptr <=
'Z') {
48 for (i=0; i<12; i+=2) {
62 for (
int i=0; i<12; i+=2) {
72 "Elo",
"Rating",
"Rapid",
"ICCF",
"USCF",
"DWZ",
"ECF",
74 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
109 else sprintf (str,
"$%u", nag);
123 strcpy(str,
"<i>(D)</i>");
125 str[0] =
'D'; str[1] = 0;
141 auto slen = std::distance(strview.first, strview.second);
142 if (slen == 0 || slen > 7)
145 char strbuf[8] = {0};
146 std::copy_n(strview.first, slen, strbuf);
147 const char* str = strbuf;
153 if ((*str <= '9' && *str >=
'0')) {
179 if (*str ==
'-' && str[1] == 0) {
182 if (*str ==
'/' && str[1] ==
'-') {
184 if (*str ==
'/' && str[1] ==
'=') {
186 if (*str ==
'-' && str[1] ==
'-') {
196 if (*str ==
'/' && str[1] ==
'+') {
198 if (*str ==
'/' && str[1] ==
'&') {
208 if (*str ==
'/' && str[1] ==
'+') {
210 if (*str ==
'-' && str[1] ==
'+') {
212 if (*str ==
'-' && str[1] == 0) {
257 if (*str ==
'-' && str[1] ==
'o') {
259 if (*str ==
'o' && str[1] == 0) {
261 if (*str ==
'^' && str[1] == 0) {
269 if (*str ==
'_' && str[1] ==
')') {
277 if (*str ==
']' && str[1] == 0) {
279 if (*str ==
'+' && str[1] ==
']') {
282 str[1] ==
'+' && str[2] ==
']') {
290 if (*str ==
'|' && str[1] ==
'_') {
292 if (*str ==
'|' && str[1] == 0) {
300 if (*str ==
'|' ) {
return NAG_Etc; }
301 if (*str ==
'_') {
return NAG_With; }
309 if (*str ==
'>' && str[1] == 0) {
311 if (*str ==
'>' && str[1] ==
'>') {
320 if (*str ==
'<' && str[1] == 0) {
325 str[1] ==
'>' && str[2] == 0) {
return NAG_File; }
331 str[1] ==
'+' && str[2] ==
'>' && str[3] == 0) {
return NAG_CounterPlay; }
341 if (*str ==
'~' && *(str+1) ==
'=') {
355 if (str[0] ==
'N' && str[1] == 0) {
360 if (str[0] ==
'D' && str[1] == 0) {
370 if (nag == 0) {
return OK; }
372 if( nag >= 1 && nag <= 6)
374 if( m->
nags[i] >= 1 && m->
nags[i] <= 6)
380 if( nag >= 10 && nag <= 21)
382 if( m->
nags[i] >= 10 && m->
nags[i] <= 21)
387 if( nag >= 1 && nag <= 6)
405 if( m->
nags[i] >= 1 && m->
nags[i] <= 6)
416 if( m->
nags[i] >= 10 && m->
nags[i] <= 21)
438 moveT* Game::allocMove() {
443 return moveChunks_.front().get() + moveChunkUsed_++;
447 moveT* res = allocMove();
454 extraTags_ = obj.extraTags_;
455 WhiteStr = obj.WhiteStr;
456 BlackStr = obj.BlackStr;
457 EventStr = obj.EventStr;
458 SiteStr = obj.SiteStr;
459 RoundStr = obj.RoundStr;
461 EventDate = obj.EventDate;
462 EcoCode = obj.EcoCode;
463 WhiteElo = obj.WhiteElo;
464 BlackElo = obj.BlackElo;
465 WhiteRatingType = obj.WhiteRatingType;
466 BlackRatingType = obj.BlackRatingType;
468 std::copy_n(obj.ScidFlags,
sizeof(obj.ScidFlags), ScidFlags);
471 StartPos = std::make_unique<Position>(*obj.StartPos);
473 NumHalfMoves = obj.NumHalfMoves;
474 PromotionsFlag = obj.PromotionsFlag;
475 KeepDecodedMoves = obj.KeepDecodedMoves;
476 WhiteEstimateElo = obj.WhiteEstimateElo;
477 BlackEstimateElo = obj.BlackEstimateElo;
478 NumMovesPrinted = obj.NumMovesPrinted;
479 PgnStyle = obj.PgnStyle;
480 PgnFormat = obj.PgnFormat;
481 HtmlStyle = obj.HtmlStyle;
484 FirstMove = obj.FirstMove->
cloneLine(
nullptr,
485 [
this]() {
return allocMove(); });
495 for (
auto& chunk : moveChunks_) {
497 moveT* end = (chunk == moveChunks_.front()) ? move + moveChunkUsed_
499 for (; move != end; ++
move) {
509 std::fill_n(move->
nags,
sizeof(move->
nags), 0);
517 void Game::ClearMoves() {
519 if (moveChunks_.empty()) {
522 moveChunks_.erase_after(moveChunks_.begin(), moveChunks_.end());
526 CurrentPos->StdStart();
531 FirstMove->
setNext(CurrentMove);
551 WhiteElo = BlackElo = 0;
552 WhiteEstimateElo = BlackEstimateElo = 0;
553 WhiteRatingType = BlackRatingType =
RATING_Elo;
563 KeepDecodedMoves =
true;
564 PromotionsFlag =
false;
605 auto pos = std::make_unique<Position>();
606 errorT err = pos->ReadFromFEN (fenStr);
612 *CurrentPos = *StartPos;
621 for (
auto& e : extraTags_) {
622 if (e.first == tag) {
623 e.second.assign(value);
627 extraTags_.emplace_back(tag, value);
635 for (
auto& e : extraTags_) {
637 return e.second.c_str();
646 auto it = std::remove_if(extraTags_.begin(), extraTags_.end(),
647 [&](
const std::pair<std::string, std::string>& e) {
648 return e.first == tag;
650 if (it != extraTags_.end()) {
651 extraTags_.erase(it, extraTags_.end());
659 if (std::equal(tag, tag + 5,
"Event"))
661 if (std::equal(tag, tag + 5,
"Round"))
663 if (std::equal(tag, tag + 5,
"White"))
665 if (std::equal(tag, tag + 5,
"Black"))
667 }
else if (tagLen == 4) {
668 if (std::equal(tag, tag + 4,
"Site"))
672 for (
auto& elem : extraTags_) {
673 if (std::equal(tag, tag + tagLen, elem.first.begin(), elem.first.end()))
676 extraTags_.emplace_back();
677 extraTags_.back().first.assign(tag, tagLen);
678 return extraTags_.back().second;
689 ASSERT (CurrentMove != NULL && CurrentMove->
prev != NULL);
691 if (comment == NULL) {
700 std::pair<const char*, const char*> rating) {
702 const size_t ratingSz = 7;
703 auto it = std::find_if(begin, begin + ratingSz, [&](
auto rType) {
704 return std::equal(ratingType, ratingType + ratingTypeLen, rType,
705 rType + std::strlen(rType));
707 byte rType =
static_cast<byte>(std::distance(begin, it));
708 if (rType >= ratingSz)
712 auto elo =
strGetUnsigned(std::string{rating.first, rating.second}.c_str());
746 CurrentPos->DoSimpleMove(&CurrentMove->
moveData);
747 CurrentMove = CurrentMove->
next;
763 CurrentMove = CurrentMove->
prev;
764 CurrentPos->UndoSimpleMove(&CurrentMove->
moveData);
776 for (
auto subVar = CurrentMove; subVar->
varChild; --varNumber) {
777 subVar = subVar->varChild;
778 if (varNumber == 0) {
779 CurrentMove = subVar->
next;
803 CurrentMove = CurrentMove->
getParent().first;
817 *CurrentPos = *StartPos;
819 CurrentPos->StdStart();
822 CurrentMove = FirstMove->
next;
849 for (
unsigned loc = 1; loc < stopLocation; ++loc) {
859 const moveT* last_move = CurrentMove->
prev;
922 CurrentMove = newVar->
next;
936 auto root = parent.first;
940 root->detachChild(parent.second);
941 root->insertChild(parent.second, 0);
951 auto root = parent.first;
954 if (parent.second->next->endMarker())
958 root->detachChild(parent.second);
959 root->insertChild(parent.second, 0);
962 root->swapLine(*parent.second->next);
972 byte tempPawnList[9];
973 MakeHomePawnList(tempPawnList);
988 auto root = parent.first;
992 root->detachChild(parent.second);
1009 CurrentMove = endMove;
1026 auto pos = std::make_unique<Position>();
1027 if (pos->ReadFromFEN(tempStr) !=
OK)
1035 *CurrentPos = *StartPos;
1036 FirstMove->
setNext(CurrentMove);
1047 bool Game::MakeHomePawnList(
byte* pbPawnList) {
1048 ASSERT(pbPawnList !=
nullptr);
1050 std::fill_n(pbPawnList, 9, 0);
1056 byte* pbList = pbPawnList +1;
1059 PromotionsFlag =
false;
1060 bool UnderPromosFlag =
false;
1064 uint hpNew = CurrentPos->GetHPSig();
1065 uint changed = hpOld - hpNew;
1068 uint changeValue = 0;
1070 changed = changed >> 1;
1071 if (changed == 0)
break;
1077 if (halfByte == 0) {
1078 *pbList = (changeValue << 4); halfByte = 1;
1080 *pbList |= (changeValue & 15); pbList++; halfByte = 0;
1087 PromotionsFlag =
true;
1089 UnderPromosFlag =
true;
1094 if (err ==
OK) { NumHalfMoves++; }
1097 pbPawnList[0] = (
byte) count;
1099 return UnderPromosFlag;
1112 if (*bd == pawn) { result |= 128; } bd--;
1113 if (*bd == pawn) { result |= 64; } bd--;
1114 if (*bd == pawn) { result |= 32; } bd--;
1115 if (*bd == pawn) { result |= 16; } bd--;
1116 if (*bd == pawn) { result |= 8; } bd--;
1117 if (*bd == pawn) { result |= 4; } bd--;
1118 if (*bd == pawn) { result |= 2; } bd--;
1119 if (*bd == pawn) { result |= 1; }
1130 while (ptn != NULL) {
1137 for (
uint i=0; i < 8; i++, sq += 8) {
1138 if (board[sq] == ptn->
pieceMatch) { found = 1;
break; }
1140 if (found != ptn->
flag) {
return 0; }
1148 for (
uint i=0; i < 8; i++, sq++) {
1149 if (board[sq] == ptn->
pieceMatch) { found = 1;
break; }
1151 if (found != ptn->
flag) {
return 0; }
1155 if (board[sq] == ptn->
pieceMatch) { found = 1; }
1156 if (found != ptn->
flag) {
return 0; }
1177 patternT * patterns,
int minPly,
int maxPly,
1178 int matchLength,
bool oppBishops,
bool sameBishops,
1179 int minDiff,
int maxDiff)
1190 KeepDecodedMoves =
false;
1193 ASSERT (matchLength >= 1);
1195 int matchesNeeded = matchLength;
1199 bool foundMatch =
false;
1200 byte wMinor, bMinor;
1204 if (CurrentPos->PieceCount(
WP) < min[
WP]) {
return false; }
1205 if (CurrentPos->PieceCount(
BP) < min[
BP]) {
return false; }
1208 if ((
int)plyCount > maxPly) {
return false; }
1209 if ((
int)plyCount < minPly) {
goto Next_Move; }
1214 if (CurrentPos->PieceCount(
WQ) < min[
WQ]) {
goto Check_Promotions; }
1215 if (CurrentPos->PieceCount(
BQ) < min[
BQ]) {
goto Check_Promotions; }
1216 if (CurrentPos->PieceCount(
WR) < min[
WR]) {
goto Check_Promotions; }
1217 if (CurrentPos->PieceCount(
BR) < min[
BR]) {
goto Check_Promotions; }
1218 if (CurrentPos->PieceCount(
WB) < min[
WB]) {
goto Check_Promotions; }
1219 if (CurrentPos->PieceCount(
BB) < min[
BB]) {
goto Check_Promotions; }
1220 if (CurrentPos->PieceCount(
WN) < min[
WN]) {
goto Check_Promotions; }
1221 if (CurrentPos->PieceCount(
BN) < min[
BN]) {
goto Check_Promotions; }
1222 wMinor = CurrentPos->PieceCount(
WB) + CurrentPos->PieceCount(
WN);
1223 bMinor = CurrentPos->PieceCount(
BB) + CurrentPos->PieceCount(
BN);
1224 if (wMinor < min[
WM]) {
goto Check_Promotions; }
1225 if (bMinor < min[
BM]) {
goto Check_Promotions; }
1228 if (CurrentPos->PieceCount(
WQ) > max[
WQ]) {
goto Next_Move; }
1229 if (CurrentPos->PieceCount(
BQ) > max[
BQ]) {
goto Next_Move; }
1230 if (CurrentPos->PieceCount(
WR) > max[
WR]) {
goto Next_Move; }
1231 if (CurrentPos->PieceCount(
BR) > max[
BR]) {
goto Next_Move; }
1232 if (CurrentPos->PieceCount(
WB) > max[
WB]) {
goto Next_Move; }
1233 if (CurrentPos->PieceCount(
BB) > max[
BB]) {
goto Next_Move; }
1234 if (CurrentPos->PieceCount(
WN) > max[
WN]) {
goto Next_Move; }
1235 if (CurrentPos->PieceCount(
BN) > max[
BN]) {
goto Next_Move; }
1236 if (CurrentPos->PieceCount(
WP) > max[
WP]) {
goto Next_Move; }
1237 if (CurrentPos->PieceCount(
BP) > max[
BP]) {
goto Next_Move; }
1238 if (wMinor > max[WM]) {
goto Next_Move; }
1239 if (bMinor > max[BM]) {
goto Next_Move; }
1243 if (CurrentPos->PieceCount(
WB) == 1
1244 && CurrentPos->PieceCount(
BB) == 1) {
1245 if (!oppBishops || !sameBishops) {
1251 const pieceT* bd = CurrentPos->GetBoard();
1255 }
else if (bd[
sq] ==
BB) {
1264 if (oppBishops && blackBishCol == whiteBishCol) {
1267 if (sameBishops && blackBishCol != whiteBishCol) {
1274 matDiff = (int)CurrentPos->MaterialValue(
WHITE) -
1275 (int)CurrentPos->MaterialValue(
BLACK);
1276 if (matDiff < minDiff || matDiff > maxDiff) {
goto Next_Move; }
1279 if (patterns == NULL || patternsMatch(
currentPos(), patterns)) {
1282 if (matchesNeeded <= 0) {
return true; }
1289 if (! PromotionsFlag) {
return false; }
1301 if (! foundMatch) { matchesNeeded = matchLength; }
1329 KeepDecodedMoves =
false;
1334 uint search_whiteHPawns = 0;
1335 uint search_blackHPawns = 0;
1336 uint current_whiteHPawns, current_blackHPawns;
1337 bool check_pawnMaskWhite, check_pawnMaskBlack;
1338 bool doHomePawnChecks =
false;
1340 uint wpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};
1341 uint bpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};;
1349 }
else if (*board ==
BP) {
1352 fyle = (fyle + 1) & 7;
1358 if (neverMatch == NULL) { neverMatch = &dummy; }
1359 *neverMatch =
false;
1363 doHomePawnChecks =
true;
1364 search_whiteHPawns = calcHomePawnMask (
WP, searchPos->
GetBoard());
1365 search_blackHPawns = calcHomePawnMask (
BP, searchPos->
GetBoard());
1367 check_pawnMaskWhite = check_pawnMaskBlack =
false;
1370 const pieceT* currentBoard = CurrentPos->GetBoard();
1372 const pieceT* b1 = currentBoard;
1401 if (check_pawnMaskWhite) {
1402 current_whiteHPawns = calcHomePawnMask (
WP, currentBoard);
1403 if ((current_whiteHPawns & search_whiteHPawns)
1404 != search_whiteHPawns) {
1409 if (check_pawnMaskBlack) {
1410 current_blackHPawns = calcHomePawnMask (
BP, currentBoard);
1411 if ((current_blackHPawns & search_blackHPawns)
1412 != search_blackHPawns) {
1418 #endif // #ifndef NO_SPEEDUPS 1421 if (searchPos->
GetToMove() != CurrentPos->GetToMove()) {
1449 if (searchPos->
HashValue() == CurrentPos->HashValue()) {
1451 if (*b1 != *b2) { found =
false;
break; }
1457 if (searchPos->
PawnHashValue() == CurrentPos->PawnHashValue()) {
1459 if (*b1 != *b2 && (*b1 ==
WP || *b1 ==
BP)) {
1469 if (searchPos->
FyleCount(
WP,f) != CurrentPos->FyleCount(
WP,f)
1470 || searchPos->
FyleCount(
BP,f) != CurrentPos->FyleCount(
BP,f)) {
1500 CurrentPos->UndoSimpleMove (sm);
1509 if (doHomePawnChecks) {
1510 check_pawnMaskWhite =
false;
1511 check_pawnMaskBlack =
false;
1517 check_pawnMaskWhite =
true;
1520 check_pawnMaskBlack =
true;
1548 uint wpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};
1549 uint bpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};;
1557 }
else if (*board ==
BP) {
1560 fyle = (fyle + 1) & 7;
1568 if (searchPos->
GetToMove() == CurrentPos->GetToMove()
1582 const pieceT* b1 = CurrentPos->GetBoard();
1586 if (*b1 != *b2 && (*b1 ==
WP || *b1 ==
BP)) {
1587 match =
false;
break;
1591 uint wpf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1592 uint bpf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1597 if (wpf[fyle] > wpawnFyle[fyle]) { match =
false;
break; }
1598 }
else if (*b1 ==
BP) {
1600 if (bpf[fyle] > bpawnFyle[fyle]) { match =
false;
break; }
1602 fyle = (fyle + 1) & 7;
1605 if (searchPos->
HashValue() == CurrentPos->HashValue()) {
1607 if (*b1 != *b2) { match =
false;
break; }
1616 if (match) {
return true; }
1623 if (match) {
return true; }
1647 for (
uint i=0; i < plyCount; i++) {
1651 if (i != 0) { outStr->
Append (
" "); }
1652 if (i == 0 || CurrentPos->GetToMove() ==
WHITE) {
1653 sprintf (temp,
"%d%s", CurrentPos->GetFullMoveCount(),
1654 (CurrentPos->GetToMove() ==
WHITE ?
"." :
"..."));
1657 moveT * m = CurrentMove;
1658 if (m->
san[0] == 0) {
1659 CurrentPos->MakeSANString(&(m->
moveData),
1679 if (!CurrentMove->
endMarker() && *CurrentMove->
san ==
'\0') {
1680 CurrentPos->MakeSANString(
1684 return CurrentMove->
san;
1709 if (m->
san[0] == 0) {
1714 strcpy (str, m->
san);
1741 moveT * m = CurrentMove;
1746 CurrentPos->MakeUCIString (&(m->
moveData), str);
1760 if (comment == NULL)
1763 if (comment[0] ==
'\0')
1771 while (tmp[0] != 0) {
1772 if (tmp[0] !=
' ') {
1790 const char * comment,
const char * postStr)
1799 s = (
char *) comment;
1828 if (PgnStyle & PGN_STYLE_STRIP_MARKS) {
1839 bool printMoveNum,
bool inComment) {
1841 const char * preCommentStr =
"{";
1842 const char * postCommentStr =
"}";
1843 const char * startTable =
"\n";
1844 const char * startColumn =
"\t";
1845 const char * nextColumn =
"\t";
1846 const char * endColumn =
"\n";
1847 const char * endTable =
"\n";
1848 bool printDiagrams =
false;
1852 postCommentStr =
"";
1853 startTable =
"<table width=\"50%\">\n";
1854 startColumn =
"<tr align=left>\n <td width=\"15%\"><b>";
1855 nextColumn =
"</b></td>\n <td width=\"45%\" align=left><b>";
1856 endColumn =
"</b></td>\n</tr>\n";
1857 endTable =
"</table>\n";
1858 printDiagrams =
true;
1861 preCommentStr =
"\\begin{nochess}{\\rm ";
1862 postCommentStr =
"}\\end{nochess}";
1863 startTable =
"\n\\begin{tabular}{p{1cm}p{2cm}p{2cm}}\n";
1866 endColumn =
"\\\\\n";
1867 endTable =
"\\end{tabular}\n\n";
1868 printDiagrams =
true;
1871 startTable =
"<br>";
1882 postCommentStr =
"";
1884 moveT * m = CurrentMove;
1892 postCommentStr =
"";
1896 if ((VarDepth > 0 || CurrentMove->
prev == FirstMove) &&
1913 moveT *m = CurrentMove;
1914 bool commentLine =
false;
1916 if (m->
san[0] == 0) {
1918 CurrentPos->MakeSANString(
1923 bool printThisMove =
true;
1927 printThisMove =
false;
1928 printMoveNum =
true;
1932 if ((PgnStyle & PGN_STYLE_NO_NULL_MOVES) &&
IsPlainFormat()) {
1939 postCommentStr =
"";
1941 printThisMove =
false;
1942 printMoveNum =
true;
1948 if (printThisMove) {
1955 if (printMoveNum || (CurrentPos->GetToMove() ==
WHITE)) {
1956 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
1959 sprintf (temp,
"%4u.", CurrentPos->GetFullMoveCount());
1961 if (CurrentPos->GetToMove() ==
BLACK) {
1972 tb->
PrintInt(CurrentPos->GetFullMoveCount(), (CurrentPos->GetToMove() ==
WHITE ?
"." :
". ..."));
1974 tb->
PrintInt(CurrentPos->GetFullMoveCount(), (CurrentPos->GetToMove() ==
WHITE ?
"." :
"..."));
1976 if (PgnStyle & PGN_STYLE_MOVENUM_SPACE) {
1984 printMoveNum =
false;
1989 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
1998 for (
char const* p = m->
san; *p; ++p) {
1999 ASSERT(q - buf < static_cast<std::ptrdiff_t>(
sizeof(buf) - 4));
2002 case 'K': q = std::copy_n(
"\xe2\x99\x94", 3, q);
break;
2003 case 'Q': q = std::copy_n(
"\xe2\x99\x95", 3, q);
break;
2004 case 'R': q = std::copy_n(
"\xe2\x99\x96", 3, q);
break;
2005 case 'B': q = std::copy_n(
"\xe2\x99\x97", 3, q);
break;
2006 case 'N': q = std::copy_n(
"\xe2\x99\x98", 3, q);
break;
2007 case 'P': q = std::copy_n(
"\xe2\x99\x99", 3, q);
break;
2008 default: *q++ = *p;
break;
2016 strcpy(tempTrans, m->
san);
2021 colWidth -= (int) std::strlen(m->
san);
2027 bool endedColumn =
false;
2032 bool printDiagramHere =
false;
2045 if (i > 0 || (temp[0] !=
'!' && temp[0] !=
'?')) {
2050 printDiagramHere =
true;
2053 colWidth -= (int) std::strlen(temp);
2061 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
2067 if (printDiagramHere) {
2068 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
2069 if (! endedColumn) {
2070 if (CurrentPos->GetToMove() ==
WHITE) {
2096 CurrentPos->DumpHtmlBoard (dstr, HtmlStyle, NULL);
2098 CurrentPos->DumpLatexBoard (dstr);
2109 printMoveNum =
true;
2123 postCommentStr =
"";
2154 if ((PgnStyle & PGN_STYLE_INDENT_COMMENTS) && VarDepth == 0) {
2171 CurrentPos->DumpHtmlBoard (dstr, HtmlStyle, NULL);
2173 CurrentPos->DumpLatexBoard (dstr);
2185 printMoveNum =
true;
2193 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
2194 if (! endedColumn) {
2195 if (CurrentPos->GetToMove() ==
WHITE) {
2211 if ( !commentLine ) {
2216 if (PgnStyle & PGN_STYLE_INDENT_VARS) {
2229 if (VarDepth == 0) { tb->
PrintString (
"</b><dl><dd>"); }
2232 if (PgnStyle & PGN_STYLE_INDENT_VARS) {
2259 if (VarDepth == 0) { tb->
PrintString (
"</dl><b>"); }
2262 if (PgnStyle & PGN_STYLE_INDENT_VARS) {
2268 if (PgnStyle & PGN_STYLE_INDENT_VARS) {
2280 printMoveNum =
true;
2286 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
2288 if (!endedColumn && CurrentPos->GetToMove() ==
BLACK) {
2297 if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) {
2310 const char * newline =
"\n";
2376 sprintf (temp,
" (%u)", WhiteElo);
2379 switch (PgnFormat) {
2381 tb->
PrintString (
" -- ");
2393 sprintf (temp,
" (%u)", BlackElo);
2400 if (!RoundStr.empty() && RoundStr !=
"?") {
2407 if (!SiteStr.empty() && SiteStr !=
"?") {
2413 if (dateStr[4] ==
'.' && dateStr[5] ==
'?') { dateStr[4] = 0; }
2414 if (dateStr[7] ==
'.' && dateStr[8] ==
'?') { dateStr[7] = 0; }
2429 if (annotator != NULL) {
2430 sprintf(temp,
" (%s)", annotator);
2442 StartPos->DumpLatexBoard (&dstr);
2447 StartPos->DumpHtmlBoard (&dstr, HtmlStyle, NULL);
2450 StartPos->PrintFEN(std::copy_n(
"Position: ", 10, temp),
2452 std::strcat(temp, newline);
2463 sprintf (temp,
"[Event \"%s\"]%s",
GetEventStr(), newline);
2465 sprintf (temp,
"[Site \"%s\"]%s",
GetSiteStr(), newline);
2467 sprintf (temp,
"[Date \"%s\"]%s", dateStr, newline);
2469 sprintf (temp,
"[Round \"%s\"]%s",
GetRoundStr(), newline);
2471 sprintf (temp,
"[White \"%s\"]%s",
GetWhiteStr(), newline);
2473 sprintf (temp,
"[Black \"%s\"]%s",
GetBlackStr(), newline);
2475 sprintf (temp,
"[Result \"%s\"]%s",
RESULT_LONGSTR[Result], newline);
2481 sprintf (temp,
"[White%s \"%u\"]%s",
2486 sprintf (temp,
"[Black%s \"%u\"]%s",
2493 sprintf (temp,
"[ECO \"%s\"]%s", ecoStr, newline);
2499 sprintf (temp,
"[EventDate \"%s\"]%s", edateStr, newline);
2504 sprintf (temp,
"[ScidFlags \"%s\"]%s", ScidFlags, newline);
2509 for (
auto& e : extraTags_) {
2510 sprintf(temp,
"[%s \"%s\"]%s", e.first.c_str(),
2511 e.second.c_str(), newline);
2517 StartPos->PrintFEN(std::copy_n(
"[FEN \"", 6, temp),
FEN_ALL_FIELDS);
2518 auto it_end = std::copy_n(
"\"]", 2, temp + std::strlen(temp));
2519 std::strcpy(it_end, newline);
2534 tb->
PrintLine (
"}\n\\begin{chess}{\\bf ");
2542 NumMovesPrinted = 1;
2549 tb->
PrintString (
"}\n\\begin{center} \\hrule \\end{center}");
2562 std::pair<const char*, unsigned>
2572 if (NewLineAtEnd) tbuf.
NewLine();
2586 ASSERT (ie != NULL && nb != NULL);
2609 eloT white = WhiteElo;
2610 eloT black = BlackElo;
2611 if (white == 0) { white = WhiteEstimateElo; }
2612 if (black == 0) { black = BlackEstimateElo; }
2613 return (white + black) / 2;
2620 makeMoveByte (
byte pieceNum,
byte value)
2622 ASSERT (pieceNum <= 15 && value <= 15);
2623 return (
byte)((pieceNum & 15) << 4) | (
byte)(value & 15);
2639 int diff = (int) sm->
to - (
int) sm->
from;
2640 static const byte val[] = {
2642 1, 2, 3, 0, 0, 0, 0, 9, 4, 0, 5, 10, 0, 0, 0, 0, 6, 7, 8
2648 if (sm->
to == sm->
from) {
2649 buf->
PutByte (makeMoveByte (0, 0));
2654 ASSERT(diff >= -9 && diff <= 9 && val[diff+9] != 0);
2655 buf->
PutByte (makeMoveByte (0, val [diff + 9]));
2664 static const int sqdiff[] = {
2665 0, -9, -8, -7, -1, 1, 7, 8, 9, -2, 2
2674 sm->
to = sm->
from + sqdiff[val];
2689 int diff = (int) sm->
to - (
int) sm->
from;
2690 static const byte val[] = {
2692 1, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
2695 0, 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 7, 0, 8
2699 ASSERT (diff >= -17 && diff <= 17 && val[diff + 17] != 0);
2709 static const int sqdiff[] = {
2710 0, -17, -15, -10, -6, 6, 10, 15, 17
2713 sm->
to = sm->
from + sqdiff[val];
2773 if (rankdiff * fylediff < 0) { val += 8; }
2784 byte fyle = (val & 7);
2788 sm->
to = sm->
from - 7 * fylediff;
2790 sm->
to = sm->
from + 9 * fylediff;
2824 std::abs(sm->
to % 8 - sm->
from % 8));
2881 int diff = (int)(sm->
to) - (int)(sm->
from);
2883 if (diff < 0) { diff = -diff; }
2889 if (diff == 7) { val = 0; }
2890 else if (diff == 8) { val = 1; }
2901 val += 3 * ((sm->
promote) - 1);
2914 toSquareDiff [16] = {
2915 7,8,9, 7,8,9, 7,8,9, 7,8,9, 7,8,9, 16
2919 promoPieceFromVal [16] = {
2928 if (toMove ==
WHITE) {
2929 sm->
to = sm->
from + toSquareDiff[val];
2931 sm->
to = sm->
from - toSquareDiff[val];
2934 sm->
promote = promoPieceFromVal[val];
2944 #define ENCODE_NAG 11 2945 #define ENCODE_COMMENT 12 2946 #define ENCODE_START_MARKER 13 2947 #define ENCODE_END_MARKER 14 2948 #define ENCODE_END_GAME 15 2950 #define ENCODE_FIRST 11 2951 #define ENCODE_LAST 15 2978 sm->
from = sqList[val >> 4];
2989 err = decodePawn (val & 15, sm, pos->
GetToMove());
2992 err = decodeKnight (val & 15, sm);
2995 err = decodeRook (val & 15, sm);
2998 err = decodeBishop (val & 15, sm);
3001 err = decodeKing (val & 15, sm);
3005 err = decodeQueen (buf, val & 15, sm);
3022 static encodeFnType * encodeFn[] = {
3032 (encodeFn[pt]) (buf, sm);
3049 encodeMove (buf, m);
3063 encodeVariation (buf, subVar->
next, subVarCount, nagCount, depth+1);
3092 if (err !=
OK) {
return err; }
3093 err = DecodeVariation (buf, flags, level + 1);
3094 if (err !=
OK) {
return err; }
3096 if (err !=
OK) {
return err; }
3098 if (err !=
OK) {
return err; }
3114 if (err !=
OK) {
return err; }
3135 static const char* commonTags[255 -
MAX_TAG_LEN] = {
3137 "WhiteCountry",
"BlackCountry",
3145 "Opening",
"Variation",
3147 "Setup",
"Source",
"SetUp",
3149 NULL, NULL, NULL, NULL,
3159 template <
typename TCont>
3161 for (
auto& tag : tagList) {
3163 const char ** common = commonTags;
3164 while (*common != NULL) {
3165 if (tag.first == *common) {
3173 if (*common == NULL) {
3174 auto length = std::min(tag.first.length(),
MAX_TAG_LEN);
3179 auto valueLen = std::min<size_t>(tag.second.length(), 255);
3199 while (b != 0 && buf->
Status() ==
OK) {
3203 b = buf->
GetByte(); date = (date << 8) | b;
3204 b = buf->
GetByte(); date = (date << 8) | b;
3205 b = buf->
GetByte(); date = (date << 8) | b;
3212 char * ctag = (
char *) commonTags[b -
MAX_TAG_LEN - 1];
3216 if (storeTags) {
AddPgnTag (ctag, value); }
3223 if (storeTags) {
AddPgnTag (tag, value); }
3241 while (b != 0 && buf->
Status() ==
OK) {
3265 ASSERT(buf != NULL && m != NULL);
3270 *commentCounter += 1;
3275 encodeComments (buf, subVar, commentCounter);
3292 ASSERT (buf != NULL && m != NULL);
3305 decodeComments (buf, subVar);
3332 byte homePawnList[9];
3333 auto UnderPromosFlag = MakeHomePawnList(homePawnList);
3339 if (err !=
OK) {
return err; }
3343 if (PromotionsFlag) { flags += 2; }
3344 if (UnderPromosFlag) { flags += 4; }
3356 err = encodeVariation (buf, FirstMove->
next, &varCount, &nagCount, 0);
3357 if (err !=
OK) {
return err; }
3360 uint commentCount = 0;
3362 err = encodeComments (buf, FirstMove, &commentCount);
3382 std::copy_n(homePawnList,
sizeof(homePawnList), ie->
GetHomePawnData());
3391 uint storedLineCode = 0;
3393 uint longestMatch = 0;
3396 uint matchLength = 0;
3403 matchLength = 0;
break;
3405 gameMove = gameMove->
next;
3408 if (matchLength > longestMatch) {
3409 longestMatch = matchLength;
3414 ASSERT(storedLineCode == static_cast<byte>(storedLineCode));
3463 while (nestCount > 0) {
3484 if (!sm) { sm = &tempMove; }
3486 if (err !=
OK) {
return err; }
3487 if (KeepDecodedMoves) {
3490 CurrentPos->DoSimpleMove (sm);
3514 err = decodeTags ?
DecodeTags(buf,
true) : skipTags(buf);
3520 if (flags & 2) { PromotionsFlag =
true; }
3529 StartPos = std::make_unique<Position>();
3530 err = StartPos->ReadFromFEN (tempStr);
3535 *CurrentPos = *StartPos;
3556 err = DecodeVariation (buf, flags, 0);
3559 err = decodeComments (buf, FirstMove);
3561 return (err !=
OK) ? err : buf->
Status();
void SetNumHalfMoves(ushort b)
#define PGN_STYLE_COMMENTS
int setRating(colorT col, const char *ratingType, size_t ratingTypeLen, std::pair< const char *, const char *> rating)
void SetCommentCount(unsigned x)
errorT MoveIntoVariation(uint varNumber)
constexpr int MOVE_CHUNKSIZE
const errorT ERROR_EndOfMoveList
void SetEventStr(const char *str)
pieceT piece_Type(pieceT p)
void ClearTranslation(int ch)
const byte NAG_WithBlackAttack
const byte NAG_BlackCounterPlay
void GetPrevMoveUCI(char *str) const
#define PGN_STYLE_INDENT_COMMENTS
const byte NAG_OppositeBishops
bool SetPgnFormatFromString(const char *str)
const char * GetBlackName(const NameBase *nb) const
const byte * GetHomePawnData() const
std::string & accessTagValue(const char *tag, size_t tagLen)
#define PGN_STYLE_UNICODE
bool strEqual(const char *str1, const char *str2)
const byte NAG_SlightCounterPlay
void SetMoveComment(const char *comment)
#define PGN_STYLE_NO_NULL_MOVES
bool strIsPrefix(const char *prefix, const char *longStr)
#define GAME_DECODE_COMMENTS
const char * GetNextSAN()
bool MaterialMatch(ByteBuffer *buf, byte *min, byte *max, patternT *pattern, int minPly, int maxPly, int matchLength, bool oppBishops, bool sameBishops, int minDiff, int maxDiff)
void SetBlackRatingType(byte b)
void restoreLocation(const GameSavedPos &savedPos)
resultT GetResult() const
const squareT NULL_SQUARE
char * strDuplicate(const char *original)
static uint32_t StrToFlagMask(const char *flags)
uint FyleCount(pieceT p, fyleT f) const
const char * FindExtraTag(const char *tag) const
void SetBlackRatingType(byte b)
errorT SetStartFen(const char *fenStr)
Setup the start position from a FEN string and remove all the moves.
static FullMove getMove(uint code, uint ply=0)
const byte NAG_Compensation
const byte NAG_ExcellentMove
const char * GetWhiteName(const NameBase *nb) const
void SetWhiteElo(eloT elo)
void AddPgnTag(const char *tag, const char *value)
const char * GetEventName(const NameBase *nb) const
void SetStartFlag(bool b)
const byte NAG_SeparatedPawns
constexpr size_t MAX_TAG_LEN
const byte NAG_BishopPair
errorT DecodeNextMove(ByteBuffer *buf, simpleMoveT *sm)
const colorT BOARD_SQUARECOLOR[66]
void SetEventDate(dateT date)
const moveT * getPrevMove() const
void SetUnderPromoFlag(bool b)
errorT DecodeTags(ByteBuffer *buf, bool storeTags)
rankT square_Rank(squareT sq)
unsigned GetLocationInPGN() const
errorT encodeTags(ByteBuffer *buf, const TCont &tagList)
void strTrimMarkCodes(char *str)
const byte NAG_WhiteSlight
const errorT ERROR_NoVariation
void SetWrapColumn(uint column)
const squareT * GetList(colorT c) const
errorT MoveToLocationInPGN(unsigned stopLocation)
void MakeUCIString(simpleMoveT *sm, char *s)
void GetFixedString(char *str, size_t length)
uint GetVarNumber() const
void SetNagCount(unsigned x)
#define PGN_STYLE_INDENT_VARS
void SetStoredLineCode(byte b)
void SetResult(resultT res)
void date_DecodeToString(dateT date, char *str)
const char * ratingTypeNames[17]
void SetEcoCode(ecoT eco)
const byte NAG_ModerateKingSide
void GetNextMoveUCI(char *str)
const byte NAG_VariousMoves
void SetWhiteStr(const char *str)
const uint HPSIG_StdStart
const byte NAG_UnitedPawns
byte PieceCount(pieceT p)
const byte NAG_BlackClear
#define PGN_STYLE_MOVENUM_SPACE
bool RemoveExtraTag(const char *tag)
squareT square_Make(fyleT f, rankT r)
byte game_parseNag(std::pair< const char *, const char *> strview)
ushort GetCurrentPly() const
errorT MoveForwardInPGN()
const byte NAG_InterestingMove
const char * langPieces[]
const byte NAG_BlackDecisive
This class stores the database's names (players, events, sites and rounds).
uint GetFlagStr(char *dest, const char *flags) const
errorT RemoveNag(bool isMoveNag)
const pieceT * GetBoard() const
void SetSiteStr(const char *str)
errorT LoadStandardTags(const IndexEntry *ie, const NameBase *nb)
void appendChild(moveT *varStart)
const byte NAG_DubiousMove
void NewlinesToSpaces(bool b)
void UndoSimpleMove(simpleMoveT *sm)
bool CommentEmpty(const char *comment)
char transPiecesChar(char c)
bool strIsCasePrefix(const char *prefix, const char *longStr)
void GetTerminatedString(char **str)
void SetRoundStr(const char *str)
const byte NAG_BlackSlightCounterPlay
void SetBlackStr(const char *str)
idNumberT GetWhite() const
const char * GetBlackStr() const
const errorT ERROR_StartOfMoveList
std::pair< const char *, unsigned > WriteToPGN(uint lineWidth=0, bool NewLineAtEnd=false, bool newLineToSpaces=true)
const byte NAG_WhiteDecisive
void SetIndent(uint column)
void SetVariationCount(unsigned x)
#define PGN_STYLE_SCIDFLAGS
errorT PrintLine(const char *str)
const char * evalNagsLatex[]
const errorT ERROR_GameFull
const char * GetWhiteStr() const
byte GetWhiteRatingType() const
void SetEventDate(dateT edate)
bool ExactMatch(Position *pos, ByteBuffer *buf, simpleMoveT *sm, gameExactMatchT searchType, bool *neverMatch)
decltype(extraTags_) const & GetExtraTags() const
void eco_ToExtendedString(ecoT ecoCode, char *ecoStr)
uint32_t strGetUnsigned(const char *str)
const byte NAG_BlackSlight
const byte NAG_SlightKingSide
idNumberT GetBlack() const
const sanFlagT SAN_CHECKTEST
void PutFixedString(const char *str, size_t length)
const byte NAG_WhiteClear
void SetPromotionsFlag(bool b)
void ResumeTranslations()
uint strGetRatingType(const char *name)
void WriteComment(TextBuffer *tb, const char *preStr, const char *comment, const char *postStr)
static bool PgnFormatFromString(const char *str, gameFormatT *fmt)
GameSavedPos currentLocation() const
errorT Encode(ByteBuffer *buf, IndexEntry *ie)
eloT GetElo(idNumberT id) const
errorT PrintWord(const char *str)
errorT MoveExitVariation()
void SetWhiteElo(eloT elo)
errorT DecodeStart(ByteBuffer *buf, bool decodeTags=false)
void strip(bool variations, bool comments, bool NAGs)
void MoveToPly(int hmNumber)
void SetWhiteRatingType(byte b)
const byte NAG_BlackDecisiveCounterPlay
const char RESULT_LONGSTR[4][8]
const Position * currentPos() const
void SetFinalMatSig(matSigT ms)
const char * GetSiteStr() const
void setNext(moveT *move)
const byte NAG_WithAttack
bool VarExactMatch(Position *searchPos, gameExactMatchT searchType)
const errorT ERROR_Decode
void SetResult(resultT res)
const char * GetSiteName(const NameBase *nb) const
unsigned GetPgnOffset() const
const byte NAG_SlightQueenSide
const byte NAG_SlightCentre
errorT WriteMoveList(TextBuffer *tb, moveT *oldCurrentMove, bool printMoveNum, bool inComment)
const byte NAG_CounterPlay
const byte NAG_WhiteCrushing
errorT PrintString(const char *str)
void SetFlag(uint32_t flagMask, bool set)
void transPieces(char *s)
void SetBlackElo(eloT elo)
const char * evalNagsRegular[]
bool HasNonStandardStart(char *outFEN=nullptr) const
bool isSpecialMoveCode(byte val)
const char * GetEventStr() const
void game_printNag(byte nag, char *str, bool asSymbol, gameFormatT format)
board?ref_base? ?ref_filter?
moveT * cloneLine(moveT *parent, TNew newMove) const
errorT AddMove(const simpleMoveT *sm)
#define ENCODE_START_MARKER
byte GetBlackRatingType() const
const resultT RESULT_None
std::pair< const moveT *, const moveT * > getParent() const
const byte NAG_BlackZugZwang
void SetBlackElo(eloT elo)
const byte NAG_ModerateQueenSide
void GetPrevSAN(char *str)
void AddTranslation(char ch, const char *str)
#define PGN_STYLE_SYMBOLS
const moveT * nextMoveInPGN() const
const byte NAG_DecisiveCounterPlay
#define PGN_STYLE_SHORT_HEADER
const byte NAG_PassedPawn
const char * GetRoundStr() const
const char * GetRoundName(const NameBase *nb) const
void SetWhiteRatingType(byte b)
matSigT matsig_Make(const byte *materialCounts)
void PutTerminatedString(const char *str)
errorT GetPartialMoveList(DString *str, uint plyCount)
uint GetCount(colorT c) const
const byte NAG_BlackCrushing
#define PGN_STYLE_STRIP_MARKS
errorT PrintInt(uint i, const char *str)
errorT Decode(ByteBuffer *buf, byte flags)
const sanFlagT SAN_MATETEST
fyleT square_Fyle(squareT sq)
dateT GetEventDate() const
#define ENCODE_END_MARKER
const uint FEN_ALL_FIELDS