61 static Game * scratchGame = NULL;
62 static std::unique_ptr<PBook> ecoBook;
64 static OpTable * reports[2] = {NULL, NULL};
68 if (scratchGame != NULL)
delete scratchGame;
69 if (spellChk != NULL)
delete spellChk;
70 for (
size_t i = 0, n =
sizeof(reports) /
sizeof(reports[0]); i < n; i++) {
71 if (reports[i] != NULL)
delete reports[i];
83 int main(
int argc,
char* argv[]) {
86 scratchGame =
new Game;
98 static const char * reportTypeName[2] = {
"opening",
"player" };
99 static const uint REPORT_OPENING = 0;
100 static const uint REPORT_PLAYER = 1;
102 static char decimalPointChar =
'.';
103 static uint htmlDiagStyle = 0;
107 #define PROBE_RESULT 1 108 #define PROBE_SUMMARY 2 109 #define PROBE_REPORT 3 110 #define PROBE_OPTIMAL 4 126 Tcl_SetResult (ti, (
char *) str, TCL_STATIC);
138 sprintf (temp,
"%d", i);
139 Tcl_SetResult (ti, temp, TCL_VOLATILE);
151 sprintf (temp,
"%u", i);
152 Tcl_SetResult (ti, temp, TCL_VOLATILE);
164 sprintf (temp,
"%u", i);
165 Tcl_AppendResult (ti, temp, NULL);
177 sprintf (temp,
"%u", i);
178 Tcl_AppendElement (ti, temp);
190 sprintf (temp,
"%0*u", width, i);
191 Tcl_SetResult (ti, temp, TCL_VOLATILE);
205 Tcl_AppendResult (ti, tempStr, NULL);
216 const char * str = Tcl_GetVar2 (ti,
"tr", (
char *) name, TCL_GLOBAL_ONLY);
217 if (str == NULL) { str = defaultText; }
228 if (errorMsg != 0) Tcl_SetResult (ti, (
char*) errorMsg, TCL_STATIC);
230 Tcl_SetObjErrorCode(ti, Tcl_NewIntObj(err));
250 const char ** minorCmds)
252 ASSERT (majorCmd != NULL);
253 Tcl_AppendResult (ti,
"Invalid command: ", majorCmd,
254 " has the following minor commands:\n", NULL);
255 while (*minorCmds != NULL) {
256 Tcl_AppendResult (ti,
" ", *minorCmds,
"\n", NULL);
272 return translate (ti,
"ErrNotOpen",
"This is not an open database.");
278 return translate (ti,
"ErrSearchInterrupted",
279 "[Interrupted search; results are incomplete]");
297 return errorResult (ti,
"Usage: strIsPrefix <shortStr> <longStr>");
311 return errorResult (ti,
"Usage: strPrefixLen <str> <str>");
358 fwrite(pgn.first, 1, pgn.second, exportFile);
371 FILE * exportFile = NULL;
372 bool exportFilter =
false;
373 bool appendToFile =
false;
375 const char * startText =
"";
376 const char * endText =
"";
377 const char * usage =
"Usage: sc_base export current|filter PGN|HTML|LaTeX <pgn_filename> options...";
380 const char * options[] = {
381 "-append",
"-starttext",
"-endtext",
"-comments",
"-variations",
382 "-spaces",
"-symbols",
"-indentComments",
"-indentVariations",
383 "-column",
"-noMarkCodes",
"-convertNullMoves", NULL
386 OPT_APPEND, OPT_STARTTEXT, OPT_ENDTEXT, OPT_COMMENTS, OPT_VARIATIONS,
387 OPT_SPACES, OPT_SYMBOLS, OPT_INDENTC, OPT_INDENTV,
388 OPT_COLUMN, OPT_NOMARKS, OPT_CONVERTNULL
394 exportFilter =
false;
405 if (exportFilter && !db->
inUse) {
409 const char * exportFileName = argv[4];
412 if ((argc % 2) != 1) {
return errorResult (ti, usage); }
415 for (
int arg = 5; arg < argc; arg += 2) {
416 const char * value = argv[arg+1];
465 case OPT_CONVERTNULL:
473 exportFile = fopen (exportFileName, (appendToFile ?
"r+" :
"w"));
474 if (exportFile == NULL) {
475 return errorResult (ti,
"Error opening file for exporting games.");
480 fseek (exportFile, 0, SEEK_END);
482 fseek (exportFile, 0, SEEK_SET);
483 const char * endMarker =
"";
485 endMarker =
"</body>";
487 endMarker =
"\\end{document}";
492 char* err = fgets(line, 1024, exportFile);
493 if (err == 0 || feof(exportFile))
break;
499 pos = ftell (exportFile);
501 fseek (exportFile, pos, SEEK_SET);
504 fputs (startText, exportFile);
513 Game * g = scratchGame;
516 if (++numSeen % 1024 == 0) {
517 if (!progress.
report(numSeen, numToExport))
break;
530 exportGame (g, exportFile, outputFormat, pgnStyle);
535 fputs (endText, exportFile);
549 "Usage: sc_base piecetrack [-g|-t] <minMoves> <maxMoves> <startSquare ...>";
556 bool timeOnSquareMode =
false;
558 if (argv[arg][0] ==
'-') {
559 if (argv[arg][1] ==
'g' &&
strIsPrefix (argv[arg],
"-games")) {
560 timeOnSquareMode =
false;
562 }
else if (argv[arg][1] ==
't' &&
strIsPrefix (argv[arg],
"-time")) {
563 timeOnSquareMode =
true;
577 if (minPly < 2) { minPly=2; }
578 if (maxPly < minPly) { maxPly = minPly; }
582 uint sqFreq[64] = {0};
583 bool trackSquare[64] = {
false };
584 int nTrackSquares = 0;
585 for (
int a=arg; a < argc; a++) {
588 if (!trackSquare[sq]) {
590 trackSquare[
sq] =
true;
609 for (
uint gnum = 0, n = db->
numGames(); gnum < n; gnum++) {
614 if ((filterSeen++ % 1000) == 0) {
615 if (!progress.
report(filterSeen, filterCount)) {
630 bool movedTo[64] = {
false };
632 int ntrack = nTrackSquares;
635 Game * g = scratchGame;
649 while (plyCount < maxPly) {
657 if (fromSquare ==
E1) {
658 if (toSquare ==
G1 && track[
H1]) {
659 fromSquare =
H1; toSquare =
F1;
661 if (toSquare ==
C1 && track[
A1]) {
662 fromSquare =
A1; toSquare =
D1;
665 if (fromSquare ==
E8) {
666 if (toSquare ==
G8 && track[
H8]) {
667 fromSquare =
H8; toSquare =
F8;
669 if (toSquare ==
C8 && track[
A8]) {
670 fromSquare =
A8; toSquare =
D8;
677 if (track[toSquare]) {
679 track[toSquare] =
false;
681 if (ntrack <= 0) {
break; }
683 }
else if (track[fromSquare]) {
685 track[fromSquare] =
false;
686 track[toSquare] =
true;
687 if (plyCount >= minPly) {
692 if (!timeOnSquareMode && !movedTo[toSquare]) {
695 movedTo[toSquare] =
true;
699 if (timeOnSquareMode && plyCount >= minPly) {
704 for (
uint i=0; i < 64; i++) {
710 if (nleft <= 0) {
break; }
723 for (
uint i=0; i < 64; i++) {
792 if (a[0] != b[0] || a[1] != b[1] || a[2] != b[2]) {
return false; }
815 if (!
hpSig_Prefix (hpData1, hpData2)) {
return false; }
841 bool skipShortGames =
false;
842 bool keepAllCommentedGames =
true;
843 bool keepAllGamesWithVars =
true;
844 bool setFilterToDups =
false;
845 bool onlyFilterGames =
false;
846 bool copyRatings =
false;
850 enum deleteStrategyT { DELETE_SHORTER, DELETE_OLDER, DELETE_NEWER };
851 deleteStrategyT deleteStrategy = DELETE_SHORTER;
855 const char * options[] = {
856 "-players",
"-colors",
"-event",
"-site",
"-round",
"-year",
857 "-month",
"-day",
"-result",
"-eco",
"-moves",
"-skipshort",
858 "-comments",
"-variations",
"-setfilter",
"-usefilter",
859 "-copyratings",
"-delete",
863 OPT_PLAYERS, OPT_COLORS, OPT_EVENT, OPT_SITE, OPT_ROUND, OPT_YEAR,
864 OPT_MONTH, OPT_DAY, OPT_RESULT, OPT_ECO, OPT_MOVES, OPT_SKIPSHORT,
865 OPT_COMMENTS, OPT_VARIATIONS, OPT_SETFILTER, OPT_USEFILTER,
866 OPT_COPYRATINGS, OPT_DELETE
869 for (
int arg = 3; arg < argc; arg += 2) {
870 const char * optStr = argv[arg];
871 const char * valueStr = argv[arg + 1];
875 case OPT_PLAYERS: criteria.
exactNames = b;
break;
876 case OPT_COLORS: criteria.
sameColors = b;
break;
877 case OPT_EVENT: criteria.
sameEvent = b;
break;
878 case OPT_SITE: criteria.
sameSite = b;
break;
879 case OPT_ROUND: criteria.
sameRound = b;
break;
880 case OPT_YEAR: criteria.
sameYear = b;
break;
881 case OPT_MONTH: criteria.
sameMonth = b;
break;
882 case OPT_DAY: criteria.
sameDay = b;
break;
883 case OPT_RESULT: criteria.
sameResult = b;
break;
885 case OPT_MOVES: criteria.
sameMoves = b;
break;
886 case OPT_SKIPSHORT: skipShortGames = b;
break;
887 case OPT_COMMENTS: keepAllCommentedGames = b;
break;
888 case OPT_VARIATIONS: keepAllGamesWithVars = b;
break;
889 case OPT_SETFILTER: setFilterToDups = b;
break;
890 case OPT_USEFILTER: onlyFilterGames = b;
break;
891 case OPT_COPYRATINGS: copyRatings = b;
break;
894 deleteStrategy = DELETE_SHORTER;
896 deleteStrategy = DELETE_OLDER;
898 deleteStrategy = DELETE_NEWER;
907 uint deletedCount = 0;
911 uint* duplicates =
new uint [numGames];
912 std::fill(duplicates, duplicates + numGames, 0);
916 std::vector<gNumListT>
hash(numGames);
918 const std::vector<uint32_t>& hashMap = (criteria.
exactNames)
919 ? std::vector<uint32_t>()
921 for (
gamenumT i=0; i < numGames; i++) {
925 && (!onlyFilterGames || dbase->
dbFilter->
Get(i) > 0)) {
937 node->
hash = (uint64_t(wh) << 32) + bl;
950 for (
size_t i=0; i < n_hash; i++) {
951 if ((i % 1024) == 0) {
952 if (!progress.
report(i, numGames))
break;
957 for (
size_t comp=i+1; comp < n_hash; comp++) {
959 if (compare->
hash != head->
hash)
break;
969 bool headImmune =
false;
970 bool compImmune =
false;
971 bool doDeletion =
false;
972 bool copiedRatings =
false;
976 if (keepAllCommentedGames) {
980 if (keepAllGamesWithVars) {
986 bool deleteHead =
false;
987 if (deleteStrategy == DELETE_OLDER) {
989 }
else if (deleteStrategy == DELETE_NEWER) {
992 ASSERT (deleteStrategy == DELETE_SHORTER);
995 deleteHead = (a <= b);
996 if (a == b && headImmune) deleteHead =
false;
1004 doDeletion = ! headImmune;
1008 gnumDelete = compare->
gNumber;
1010 doDeletion = ! compImmune;
1022 copiedRatings =
true;
1031 copiedRatings =
true;
1035 if (copiedRatings) {
1038 if (setFilterToDups) {
1050 return deletedCount;
1070 sc_base_tag (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
1072 const char * usage =
"Usage: sc_base tag [filter <tagname> | list | strip <tagname>]";
1073 const char * options[] = {
1074 "find",
"list",
"strip", NULL
1077 TAG_FIND, TAG_LIST, TAG_STRIP
1080 const char * tag = NULL;
1081 std::vector< std::pair <std::string, uint> > tag_freq;
1092 if (argc != 3) {
return errorResult (ti, usage); }
1103 if (cmd == TAG_STRIP) {
1115 Game * g = scratchGame;
1116 uint nEditedGames = 0;
1119 if ((gnum % 1000) == 0) {
1120 if (!progress.
report(gnum, n))
break;
1131 if (cmd == TAG_FIND) {
1136 }
else if (cmd == TAG_STRIP) {
1146 ASSERT (cmd == TAG_LIST);
1150 for (
uint i=0; i < tag_freq.size(); i++) {
1151 if (tag_freq[i].first == tag.first) {
1152 tag_freq[i].second++;
1158 tag_freq.emplace_back(tag.first, 1);
1166 if (cmd == TAG_STRIP) {
1172 if (cmd == TAG_LIST) {
1173 for (
uint i=0; i < tag_freq.size(); i++) {
1174 uint freq = tag_freq[i].second;
1175 const char*
name = tag_freq[i].first.c_str();
1176 if (freq > 0 && !
strEqual (name,
"SetUp")) {
1177 Tcl_AppendElement (ti, name);
1193 sc_clipbase (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
1198 static const char * options [] = {
1199 "clear",
"paste", NULL
1202 CLIP_CLEAR, CLIP_PASTE
1216 if (db != clipbase) {
1248 sc_eco (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
1251 static const char * options [] = {
1252 "base",
"game",
"read",
"reset",
"size",
"summary",
1256 ECO_BASE, ECO_GAME, ECO_READ, ECO_RESET, ECO_SIZE, ECO_SUMMARY,
1273 if (ecoBook) { ecoBook = NULL; }
1277 return setUintResult (ti, ecoBook == NULL ? 0 : ecoBook->Size());
1308 sc_eco_base (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
1311 return errorResult (ti,
"Usage: sc_eco base <bool:all_games> <bool:extensions>");
1313 if (!ecoBook) {
return errorResult (ti,
"No ECO Book is loaded."); }
1318 enum {ECO_NOCODE, ECO_ALL, ECO_DATE, ECO_FILTER};
1320 switch (argv[2][0]) {
1323 option = ECO_NOCODE;
break;
1325 option = ECO_DATE;
break;
1327 option = ECO_FILTER;
break;
1329 option = ECO_ALL;
break;
1334 if (option == ECO_DATE) {
1340 if (ie.GetLength() == 0)
1344 if (option == ECO_NOCODE && ie.GetEcoCode() != 0)
1348 if (option == ECO_DATE && ie.GetDate() < startDate)
1354 Game* g = scratchGame;
1367 uint leastMaterial = ecoBook->FewestPieces();
1375 }
while (err ==
OK && maxPly > 0 && material >= leastMaterial);
1385 if (! extendedCodes) {
1391 }
while (err ==
OK);
1393 if (ie.GetEcoCode() != ecoCode) {
1394 ie.SetEcoCode(ecoCode);
1400 std::string filter =
1401 (option == ECO_FILTER) ?
"dbfilter" : dbase.
newFilter();
1404 if (option == ECO_FILTER)
1407 return UI_Result(ti, changes.first, changes.second);
1416 sc_eco_game (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
1423 return errorResult (ti,
"Usage: sc_game eco [ply]");
1426 if (!ecoBook) {
return TCL_OK; }
1456 sc_eco_read (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
1458 if (argc < 3) {
return TCL_OK; }
1463 Tcl_AppendResult (ti,
"Unable to open the ECO file:\n",
1466 Tcl_AppendResult (ti,
"Unable to load the ECO file:\n",
1483 if (argc != 3 && argc != 4) {
1484 return errorResult (ti,
"Usage: sc_eco summary <ECO-prefix> [<bool:color>]");
1487 if (!ecoBook) {
return TCL_OK; }
1490 bool inMoveList =
false;
1491 translateECO(ti, ecoBook->EcoSummary(argv[2]).c_str(), dstr);
1495 const char * s = oldstr->
Data();
1505 dstr->
Append (
"<blue><run importMoveList {");
1514 dstr->
Append (
"</run></blue></tab><br>");
1524 Tcl_AppendResult (ti, dstr->
Data(), NULL);
1537 return errorResult (ti,
"Usage: sc_eco translate <lang> <from> <to>");
1545 trans->
next = ecoTranslations;
1549 ecoTranslations =
trans;
1562 dstrTo->
Append (strFrom);
1563 const char *
language = Tcl_GetVar (ti,
"language", TCL_GLOBAL_ONLY);
1564 if (language == NULL) {
return; }
1565 char lang = language[0];
1566 while (trans != NULL) {
1583 my_Tcl_Free((
char*) temp);
1588 trans = trans->
next;
1605 static const char * options [] = {
1606 "count",
"first",
"frequency",
1607 "last",
"negate",
"next",
1608 "previous",
"stats",
1609 "search",
"release",
1610 "treestats",
"export",
"copy",
"and",
"or",
"new", NULL
1613 FILTER_COUNT, FILTER_FIRST, FILTER_FREQ,
1614 FILTER_LAST, FILTER_NEGATE, FILTER_NEXT,
1615 FILTER_PREV, FILTER_STATS,
1616 FILTER_SEARCH, FILTER_RELEASE,
1617 FILTER_TREESTATS, FILTER_EXPORT, FILTER_COPY, FILTER_AND, FILTER_OR, FILTER_NEW
1631 if (argc == 3 || argc == 4) {
1666 if (argc < 4)
return errorResult (ti,
"Usage: sc_filter <cmd> baseId filterName");
1668 if (dbase == NULL)
return errorResult (ti,
"sc_filter: invalid baseId");
1670 if (filter == 0)
return errorResult (ti,
"sc_filter: invalid filterName");
1677 if (filter.
get(i) != 0 && f.
get(i) == 0) filter.
set(i, 0);
1682 return errorResult (ti,
"Usage: sc_filter and baseId filterName filterAnd");
1689 if (filter.
get(i) == 0) filter.
set(i, f.
get(i));
1694 return errorResult (ti,
"Usage: sc_filter or baseId filterName filterOr");
1706 return errorResult (ti,
"Usage: sc_filter copy baseId filterTo filterFrom");
1713 filter.
set(i, ! filter.
get(i) );
1720 case FILTER_RELEASE:
1729 if (
strCompare(
"board", argv[4]) == 0 && argc == 10) {
1730 const char* args[6] = {argv[3], argv[4], argv[9], argv[5],
1735 return errorResult (ti,
"Usage: sc_filter search baseId filterName <header> [args]");
1737 case FILTER_TREESTATS: {
1741 for (
uint i=0; i < stats.size(); i++) {
1743 ginfo.push_back(stats[i].SAN);
1744 ginfo.push_back(stats[i].ngames);
1745 ginfo.push_back(stats[i].resultW);
1746 ginfo.push_back(stats[i].resultD);
1747 ginfo.push_back(stats[i].resultB);
1748 ginfo.push_back(stats[i].exp);
1749 ginfo.push_back(stats[i].nexp);
1750 if (stats[i].toMove ==
WHITE) ginfo.push_back(
"W");
1751 else ginfo.push_back(stats[i].toMove ==
BLACK ?
"B" :
" ");
1753 res.push_back(ginfo);
1759 if (argc >= 7 && argc <=9) {
1760 FILE* exportFile = fopen(argv[5],
"wb");
1761 if (exportFile == NULL)
return errorResult (ti,
"Error opening file for exporting games.");
1770 if (argc > 7) fprintf(exportFile,
"%s", argv[7]);
1773 size_t count = filter->
size();
1775 count = dbase->
listGames(argv[4], 0, count, filter, idxList);
1777 for (
size_t i = 0; i < count; ++i) {
1783 std::pair<const char*, unsigned>
pgn = g.
WriteToPGN(75,
true);
1784 if (pgn.second != fwrite(pgn.first, 1, pgn.second, exportFile)) {
1788 if ((i % 1024 == 0) && !progress.
report(i, count)) {
1793 if (err ==
OK && argc > 8)
1794 fprintf(exportFile,
"%s", argv[8]);
1795 fclose (exportFile);
1799 return errorResult (ti,
"Usage: sc_filter export baseId filterName sortCrit filename <PGN|LaTeX> [header] [footer]");
1825 const char * usage =
1826 "Usage: sc_filter freq baseId filterName date|elo|move <startDate|minElo|lowerhalfMove> [<endDate|maxElo|higherhalfMove>] [GuessElo]";
1828 bool eloMode =
false;
1829 bool moveMode =
false;
1830 bool guessElo =
true;
1831 const char * options[] = {
"date",
"elo",
"move", NULL };
1832 enum { OPT_DATE, OPT_ELO, OPT_MOVE };
1835 if (argc >= 6 && argc <= 8) {
1839 case OPT_DATE: eloMode =
false;
break;
1840 case OPT_ELO: eloMode =
true;
break;
1841 case OPT_MOVE: moveMode =
true;
break;
1849 uint maxMove, minMove;
1852 maxMove = minMove + 1;
1863 minElo = minElo + minElo;
1864 maxElo = maxElo + maxElo + 1;
1867 uint filteredCount = 0;
1871 for (
uint gnum=0, n = dbase->
numGames(); gnum < n; gnum++) {
1876 uint bothElo = wElo + bElo;
1877 if (wElo == 0 && bElo != 0) {
1878 bothElo += (bElo > 2200 ? 2200 : bElo);
1879 }
else if (bElo == 0 && wElo != 0) {
1880 bothElo += (wElo > 2200 ? 2200 : wElo);
1882 if (bothElo >= minElo && bothElo <= maxElo) {
1884 if (filter.
get(gnum) != 0) {
1892 if (mini < minElo || mini >= maxElo)
1895 if (filter.
get(gnum) != 0) {
1900 }
else if ( moveMode ) {
1902 for (
uint gnum=0, n = dbase->
numGames(); gnum < n; gnum++) {
1905 if (move >= minMove && move <= maxMove) {
1907 if (filter.
get(gnum) != 0) {
1914 for (
uint gnum=0, n = dbase->
numGames(); gnum < n; gnum++) {
1917 if (date >= startDate && date <= endDate) {
1919 if (filter.
get(gnum) != 0) {
1956 for (gnum--; gnum >= 0; gnum--) {
1971 while (nextNumber < db->numGames()) {
1989 while (prevNumber >= 0) {
2007 enum {STATS_ALL, STATS_ELO, STATS_YEAR};
2009 if (argc < 2 || argc > 5) {
2010 return errorResult (ti,
"Usage: sc_filter stats [all | elo <xx> | year <xx>]");
2012 int statType = STATS_ALL;
2017 if (argv[2][0] ==
'e') { statType = STATS_ELO; }
2018 if (argv[2][0] ==
'y') { statType = STATS_YEAR; }
2020 if (statType == STATS_ELO || statType == STATS_YEAR) {
2022 return errorResult (ti,
"Incorrect number of parameters.");
2027 if ( max > 10000 ) {
2037 if (filter.
get(i)) {
2039 if (statType == STATS_ELO &&
2043 if (statType == STATS_YEAR
2049 if (statType == STATS_ELO ) {
2052 if ( maxi < ie->GetBlackElo() ) maxi = ie->
GetBlackElo();
2053 if (maxi < min || maxi >= max)
2060 if (mini < min || mini >= max)
2064 if (statType == STATS_YEAR
2076 percentScore = total ? percentScore * 500 / total : 0;
2077 sprintf (temp,
"%7u %7u %7u %7u %3u%c%u%%",
2082 percentScore / 10, decimalPointChar, percentScore % 10);
2083 Tcl_AppendResult (ti, temp, NULL);
2091 sc_game (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
2093 static const char * options [] = {
2094 "altered",
"setaltered",
"crosstable",
"eco",
2095 "find",
"firstMoves",
"import",
2096 "info",
"load",
"merge",
"moves",
2097 "new",
"novelty",
"number",
"pgn",
2098 "pop",
"push",
"SANtoUCI",
"save",
2099 "startBoard",
"strip",
"summary",
2101 "undo",
"undoAll",
"undoPoint",
"redo", NULL
2104 GAME_ALTERED, GAME_SET_ALTERED, GAME_CROSSTABLE, GAME_ECO,
2105 GAME_FIND, GAME_FIRSTMOVES, GAME_IMPORT,
2106 GAME_INFO, GAME_LOAD, GAME_MERGE, GAME_MOVES,
2107 GAME_NEW, GAME_NOVELTY, GAME_NUMBER, GAME_PGN,
2108 GAME_POP, GAME_PUSH, GAME_SANTOUCI, GAME_SAVE,
2109 GAME_STARTBOARD, GAME_STRIP, GAME_SUMMARY,
2110 GAME_TAGS, GAME_TRUNCATE,
2111 GAME_UNDO, GAME_UNDO_ALL, GAME_UNDO_POINT, GAME_REDO
2114 char old_language = 0;
2122 case GAME_SET_ALTERED:
2124 return errorResult (ti,
"Usage: sc_game setaltered [0|1]");
2128 case GAME_CROSSTABLE:
2137 case GAME_FIRSTMOVES:
2178 errorT err = pos->ParseMove(&sm, argv[2]);
2183 pos->MakeUCIString(&sm, buf);
2186 return errorResult(ti,
"usage sc_game SANtoUCI move");
2191 case GAME_STARTBOARD:
2206 if (argc > 2 &&
strIsPrefix (argv[2],
"-start")) {
2218 if (argc > 2 &&
strCompare(
"size", argv[2]) == 0) {
2240 case GAME_UNDO_POINT:
2245 if (argc > 2 &&
strCompare(
"size", argv[2]) == 0) {
2272 if (eventDate != 0 && EventDate != 0 && EventDate != eventDate) {
2285 static const char * options [] = {
2286 "plain",
"html",
"hypertext",
"latex",
"filter",
"count", NULL
2289 OPT_PLAIN, OPT_HTML, OPT_HYPERTEXT, OPT_LATEX, OPT_FILTER, OPT_COUNT
2293 const char * usageMsg =
2294 "Usage: sc_game crosstable plain|html|hypertext|filter|count [name|rating|score|country] [allplay|swiss] [(+|-)(colors|countries|tallies|ratings|titles|groups|breaks|numcolumns)]";
2296 static const char * extraOptions [] = {
2297 "allplay",
"knockout",
"swiss",
"auto",
2298 "name",
"rating",
"score",
"country",
2300 "-breaks",
"+breaks",
2301 "-colors",
"+colors",
2302 "-countries",
"+countries",
2303 "-tallies",
"+tallies",
2304 "-ratings",
"+ratings",
2305 "-titles",
"+titles",
2306 "-groups",
"+groups",
2307 "-deleted",
"+deleted",
2308 "-numcolumns",
"+numcolumns",
2310 "-threewin",
"+threewin",
2314 EOPT_ALLPLAY, EOPT_KNOCKOUT, EOPT_SWISS, EOPT_AUTO,
2315 EOPT_SORT_NAME, EOPT_SORT_RATING, EOPT_SORT_SCORE, EOPT_SORT_COUNTRY,
2316 EOPT_AGES_OFF, EOPT_AGES_ON,
2317 EOPT_BREAKS_OFF, EOPT_BREAKS_ON,
2318 EOPT_COLORS_OFF, EOPT_COLORS_ON,
2319 EOPT_COUNTRIES_OFF, EOPT_COUNTRIES_ON,
2320 EOPT_TALLIES_OFF, EOPT_TALLIES_ON,
2321 EOPT_RATINGS_OFF, EOPT_RATINGS_ON,
2322 EOPT_TITLES_OFF, EOPT_TITLES_ON,
2323 EOPT_GROUPS_OFF, EOPT_GROUPS_ON,
2324 EOPT_DELETED_OFF, EOPT_DELETED_ON,
2325 EOPT_NUMCOLUMNS_OFF, EOPT_NUMCOLUMNS_ON,
2327 EOPT_THREEWIN_OFF, EOPT_THREEWIN_ON
2330 int sort = EOPT_SORT_SCORE;
2332 bool showAges =
true;
2333 bool showColors =
true;
2334 bool showCountries =
true;
2335 bool showTallies =
true;
2336 bool showRatings =
true;
2337 bool showTitles =
true;
2338 bool showBreaks =
false;
2339 bool scoreGroups =
false;
2340 bool useDeletedGames =
false;
2341 bool numColumns =
false;
2342 uint numTableGames = 0;
2343 uint gameNumber = 0;
2344 bool threewin =
false;
2347 if (option < 0) {
return errorResult (ti, usageMsg); }
2349 for (
int arg=3; arg < argc; arg++) {
2351 switch (extraOption) {
2356 case EOPT_SORT_NAME: sort = EOPT_SORT_NAME;
break;
2357 case EOPT_SORT_RATING: sort = EOPT_SORT_RATING;
break;
2358 case EOPT_SORT_SCORE: sort = EOPT_SORT_SCORE;
break;
2359 case EOPT_SORT_COUNTRY: sort = EOPT_SORT_COUNTRY;
break;
2360 case EOPT_AGES_OFF: showAges =
false;
break;
2361 case EOPT_AGES_ON: showAges =
true;
break;
2362 case EOPT_BREAKS_OFF: showBreaks =
false;
break;
2363 case EOPT_BREAKS_ON: showBreaks =
true;
break;
2364 case EOPT_COLORS_OFF: showColors =
false;
break;
2365 case EOPT_COLORS_ON: showColors =
true;
break;
2366 case EOPT_COUNTRIES_OFF: showCountries =
false;
break;
2367 case EOPT_COUNTRIES_ON: showCountries =
true;
break;
2368 case EOPT_TALLIES_OFF: showTallies =
false;
break;
2369 case EOPT_TALLIES_ON: showTallies =
true;
break;
2370 case EOPT_RATINGS_OFF: showRatings =
false;
break;
2371 case EOPT_RATINGS_ON: showRatings =
true;
break;
2372 case EOPT_TITLES_OFF: showTitles =
false;
break;
2373 case EOPT_TITLES_ON: showTitles =
true;
break;
2374 case EOPT_GROUPS_OFF: scoreGroups =
false;
break;
2375 case EOPT_GROUPS_ON: scoreGroups =
true;
break;
2376 case EOPT_DELETED_OFF: useDeletedGames =
false;
break;
2377 case EOPT_DELETED_ON: useDeletedGames =
true;
break;
2378 case EOPT_NUMCOLUMNS_OFF: numColumns =
false;
break;
2379 case EOPT_NUMCOLUMNS_ON: numColumns =
true;
break;
2383 if (arg+1 >= argc) {
return errorResult (ti, usageMsg); }
2387 case EOPT_THREEWIN_OFF: threewin = false ;
break;
2388 case EOPT_THREEWIN_ON: threewin = true ;
break;
2392 if (!db->
inUse) {
return TCL_OK; }
2394 const char * newlineStr =
"";
2396 case OPT_PLAIN: newlineStr =
"\n";
break;
2397 case OPT_HTML: newlineStr =
"<br>\n";
break;
2398 case OPT_HYPERTEXT: newlineStr =
"<br>";
break;
2399 case OPT_LATEX: newlineStr =
"\\\\\n";
break;
2404 if (gameNumber > 0) {
2408 return setResult (ti,
"Invalid game number");
2412 return errorResult (ti,
"Error: empty game file record.");
2415 return errorResult (ti,
"Error reading game file.");
2436 if (sort == EOPT_SORT_NAME) { ctable->
SortByName(); }
2437 if (sort == EOPT_SORT_RATING) { ctable->
SortByElo(); }
2445 ctable->
SetElos (showRatings);
2461 bool tableFullMessage =
false;
2465 if (! isCrosstableGame (ie, siteId, eventId, eventDate)) {
2474 if (whiteId == blackId) {
continue; }
2477 if (option == OPT_FILTER) {
2483 if (option == OPT_COUNT) {
2492 if (! tableFullMessage) {
2493 tableFullMessage =
true;
2494 Tcl_AppendResult (ti,
"Warning: Player limit reached; table is incomplete\n\n", NULL);
2502 ctable->
AddResult (i+1, whiteId, blackId, result, round, date);
2503 if (date < firstSeenDate) { firstSeenDate =
date; }
2504 if (date > lastSeenDate) { lastSeenDate =
date; }
2507 if (option == OPT_COUNT) {
2512 if (option == OPT_FILTER) {
2518 return setResult (ti,
"No crosstable for this game.");
2521 if (option == OPT_LATEX) {
2522 Tcl_AppendResult (ti,
"\\documentclass[10pt,a4paper]{article}\n\n",
2523 "\\usepackage{a4wide}\n\n",
2524 "\\begin{document}\n\n",
2525 "\\setlength{\\parindent}{0cm}\n",
2526 "\\setlength{\\parskip}{0.5ex}\n",
2533 uint apaLimit = 300;
2536 !tableFullMessage) {
2537 Tcl_AppendResult (ti,
"Warning: Too many players for all-play-all; try displaying as a swiss tournament.\n\n", NULL);
2542 Tcl_AppendResult (ti, stemp, NULL);
2545 Tcl_AppendResult (ti, stemp, NULL);
2546 if (lastSeenDate != firstSeenDate) {
2549 Tcl_AppendResult (ti,
" - ", stemp, NULL);
2551 Tcl_AppendResult (ti, newlineStr, NULL);
2554 if (avgElo > 0 && showRatings) {
2555 Tcl_AppendResult (ti,
translate (ti,
"AverageRating",
"Average Rating"),
2560 sprintf (stemp,
" (%s %u)",
2561 translate (ti,
"Category",
"Category"), category);
2562 Tcl_AppendResult (ti, stemp, NULL);
2564 Tcl_AppendResult (ti, newlineStr, NULL);
2571 Tcl_AppendResult (ti, dstr->
Data(), NULL);
2572 if (option == OPT_LATEX) {
2573 Tcl_AppendResult (ti,
"\n\\end{document}\n", NULL);
2593 return errorResult (ti,
"sc_game_find: Incorrect parameters");
2599 const char * whiteStr = argv[3];
2600 const char * blackStr = argv[4];
2601 const char * siteStr = argv[5];
2602 const char * roundStr = argv[6];
2607 white = black = site = round = 0;
2620 if (ie->
GetWhite() == white) { score++; }
2621 if (ie->
GetBlack() == black) { score++; }
2622 if (ie->
GetSite() == site) { score++; }
2624 if (ie->
GetYear() == year) { score++; }
2625 if (ie->
GetResult() == result) { score++; }
2636 if (ie->
GetWhite() == white) { score++; }
2637 if (ie->
GetBlack() == black) { score++; }
2638 if (ie->
GetSite() == site) { score++; }
2640 if (ie->
GetYear() == year) { score++; }
2641 if (ie->
GetResult() == result) { score++; }
2644 if (score > bestScore || (score == bestScore && gnum == i)) {
2649 if (score == 6) {
break; }
2662 return errorResult (ti,
"Usage: sc_game firstMoves <numMoves>");
2671 if (plyCount == 0) plyCount = 1;
2680 return errorResult(ti,
"Usage: sc_game import <pgn-text>");
2690 if (pgn.
log.empty())
2692 "PGN text imported with no errors or warnings.");
2695 "Errors/warnings importing PGN text:\n\n" + pgn.
log);
2707 bool showResult =
false;
2708 bool showSummary =
false;
2709 bool fullReport =
false;
2710 bool optimalMoves =
false;
2725 optimalMoves =
true;
2732 if (! fullReport) {
return false; }
2742 uint unknownCount = 0;
2750 if (showSummary || fullReport || optimalMoves) {
2753 for (
uint i=0; i < moveList.
Size(); i++) {
2756 moveFound[i] =
false;
2757 movePrinted[i] =
false;
2760 moveFound[i] =
true;
2761 moveScore[i] = newScore;
2764 }
else if (newScore == 0) {
2779 for (
uint i=0; i < moveList.
Size(); i++) {
2780 if ((score >= 0 && moveScore[i] == -score) ||
2781 (score < 0 && moveScore[i] == -score - 1)) {
2782 if (count > 0) { dstr->
Append (
" "); }
2792 sprintf (tempStr,
"+:%u =:%u -:%u ?:%u",
2793 winCount, drawCount, lossCount, unknownCount);
2795 int prevScore = -9999999;
2802 const char * bestMove =
"";
2803 for (
uint i=0; i < moveList.
Size(); i++) {
2804 if (movePrinted[i]) {
continue; }
2805 if (! moveFound[i]) {
continue; }
2806 int newScore = - moveScore[i];
2808 (newScore > 0 && bestScore <= 0) ||
2809 (newScore > 0 && newScore < bestScore) ||
2810 (newScore == 0 && bestScore < 0) ||
2811 (newScore < 0 && bestScore < 0 && newScore < bestScore) ||
2812 (newScore == bestScore &&
2816 bestScore = newScore;
2817 bestMove = sanList.
list[i];
2820 if (!found) {
break; }
2821 movePrinted[index] =
true;
2823 (bestScore > 0 && prevScore < 0) ||
2824 (bestScore == 0 && prevScore != 0) ||
2825 (bestScore < 0 && prevScore >= 0)) {
2828 const char * tag = NULL;
2829 const char * msg = NULL;
2830 if (bestScore > 0) {
2831 tag =
"WinningMoves"; msg =
"Winning moves";
2832 }
else if (bestScore < 0) {
2833 tag =
"LosingMoves"; msg =
"Losing moves";
2835 tag =
"DrawingMoves"; msg =
"Drawing moves";
2839 if (bestScore != prevScore) {
2840 if (bestScore > 0) {
2841 sprintf (tempStr,
" +%3d ", bestScore);
2842 }
else if (bestScore == 0) {
2845 sprintf (tempStr,
" -%3d ", -bestScore);
2847 dstr->
Append (
"\n", tempStr);
2851 prevScore = bestScore;
2854 if (unknownCount > 0) {
2856 dstr->
Append (
translate (ti,
"UnknownMoves",
"Unknown-result moves"));
2858 bool firstUnknown =
true;
2861 const char * bestMove =
"";
2863 for (
uint i=0; i < moveList.
Size(); i++) {
2864 if (!moveFound[i] && !movePrinted[i]) {
2868 bestMove = sanList.
list[i];
2873 if (!found) {
break; }
2874 movePrinted[index] =
true;
2875 if (!firstUnknown) {
2878 firstUnknown =
false;
2897 for (
uint i=0; i < moveList.
Size(); i++) {
2899 if (moveScore[i] == 0) {
2900 drawlist[drawcount] = sanList.
list[i];
2903 losslist[losscount] = sanList.
list[i];
2908 if (moveList.
Size() == 0) {
2910 }
else if (drawcount == moveList.
Size()) {
2912 }
else if (drawcount == 1) {
2914 dstr->
Append (
" ", drawlist[0]);
2915 }
else if (drawcount+1 == moveList.
Size() && losscount==1) {
2917 }
else if (drawcount > 0) {
2919 dstr->
Append (drawcount);
2921 if (drawcount == 1) {
2927 for (
uint m=0; m < drawcount; m++) {
2929 if (m > 0) { dstr->
Append (
", "); }
2930 dstr->
Append (drawlist[m]);
2933 if (drawcount > 3) { dstr->
Append (
", ..."); }
2935 if (losscount > 0) {
2937 if (losscount == 1) {
2938 if (losscount+drawcount == moveList.
Size()) {
2942 }
else if (drawcount < 4 &&
2943 drawcount+losscount == moveList.
Size()) {
2946 dstr->
Append (losscount);
2948 for (
uint m=0; m < losscount; m++) {
2950 if (m > 0) { dstr->
Append (
", "); }
2951 dstr->
Append (losslist[m]);
2954 if (losscount > 3) { dstr->
Append (
", ..."); }
2959 if (showResult) { dstr->
Append (
"]"); }
2961 }
else if (score > 0) {
2965 sprintf (temp,
"%s:%d [%s %s %d",
2966 toMove ==
WHITE ?
"+-" :
"-+", score,
2980 for (
uint i=0; i < moveList.
Size(); i++) {
2981 if (moveFound[i] && moveScore[i] == -score) {
2992 if (showResult) { dstr->
Append (
"]"); }
2999 sprintf (tempStr,
"# [%s %s %s",
3004 sprintf (tempStr,
"%s:%d [%s %s %d",
3005 toMove ==
WHITE ?
"-+" :
"+-", -1 - score,
3020 for (
uint i=0; i < moveList.
Size(); i++) {
3021 if (moveFound[i] && moveScore[i] == (-score - 1)) {
3031 if (showResult) { dstr->
Append (
"]"); }
3044 bool hideNextMove =
false;
3045 bool showMaterialValue =
false;
3046 bool showFEN =
false;
3047 uint commentWidth = 50;
3048 uint commentHeight = 1;
3049 bool fullComment =
false;
3054 while (arg < argc) {
3060 }
else if (
strIsPrefix (argv[arg],
"-materialValue")) {
3081 commentWidth = 99999;
3082 commentHeight = 99999;
3117 Tcl_AppendResult (ti, dateStr, NULL);
3126 Tcl_AppendResult (ti, temp, NULL);
3129 }
else if (
strIsPrefix (argv[arg],
"nextMoveNT")) {
3131 Tcl_AppendResult (ti, temp, NULL);
3134 }
else if (
strIsPrefix (argv[arg],
"nextMoveUCI")) {
3136 Tcl_AppendResult (ti, temp, NULL);
3138 }
else if (
strIsPrefix (argv[arg],
"previousMove")) {
3141 Tcl_AppendResult (ti, temp, NULL);
3144 }
else if (
strIsPrefix (argv[arg],
"previousMoveNT")) {
3146 Tcl_AppendResult (ti, temp, NULL);
3149 }
else if (
strIsPrefix (argv[arg],
"previousMoveUCI")) {
3151 Tcl_AppendResult (ti, temp, NULL);
3153 }
else if (
strIsPrefix (argv[arg],
"duplicate")) {
3161 str.append(ecoStr.first, ecoStr.second);
3168 const char * gameStr =
translate (ti,
"game");
3169 sprintf (temp,
"%c%s %u: <pi %s>%s</pi>", toupper(gameStr[0]),
3173 sprintf(temp + std::strlen(temp),
" (%s)", whCountry);
3175 Tcl_AppendResult (ti, temp, NULL);
3177 bool eloEstimated =
false;
3180 eloEstimated =
true;
3183 sprintf (temp,
" <red>%u%s</red>", elo, eloEstimated ?
"*" :
"");
3184 Tcl_AppendResult (ti, temp, NULL);
3186 sprintf (temp,
" -- <pi %s>%s</pi>",
3189 sprintf(temp + std::strlen(temp),
" (%s)", blCountry);
3191 Tcl_AppendResult (ti, temp, NULL);
3193 eloEstimated =
false;
3196 eloEstimated =
true;
3199 sprintf (temp,
" <red>%u%s</red>", elo, eloEstimated ?
"*" :
"");
3200 Tcl_AppendResult (ti, temp, NULL);
3204 sprintf (temp,
"<br>(%s: %s)",
3207 sprintf (temp,
"<br>%s <red>(%u)</red>",
3211 Tcl_AppendResult (ti, temp, NULL);
3217 strCopy (basicEcoStr, fullEcoStr);
3218 if (
strLength(basicEcoStr) >= 4) { basicEcoStr[3] = 0; }
3219 Tcl_AppendResult (ti,
" <blue><run ::windows::eco::Refresh ",
3220 basicEcoStr,
">", fullEcoStr,
3221 "</run></blue>", NULL);
3226 Tcl_AppendResult (ti,
" <red>", dateStr,
"</red>", NULL);
3232 Tcl_AppendResult (ti,
" <gray>(",
3233 translate (ti,
"deleted"),
")</gray>", NULL);
3238 const char * flagStr = userFlags;
3240 if (*flagStr ==
'D') { flagStr++; }
3241 if (*flagStr != 0) {
3242 Tcl_AppendResult (ti,
" <gray>(",
3244 ": ", flagStr, NULL);
3246 while (*flagStr != 0) {
3247 const char * flagName = NULL;
3249 case 'W': flagName =
"WhiteOpFlag";
break;
3250 case 'B': flagName =
"BlackOpFlag";
break;
3251 case 'M': flagName =
"MiddlegameFlag";
break;
3252 case 'E': flagName =
"EndgameFlag";
break;
3253 case 'N': flagName =
"NoveltyFlag";
break;
3254 case 'P': flagName =
"PawnFlag";
break;
3255 case 'T': flagName =
"TacticsFlag";
break;
3256 case 'Q': flagName =
"QsideFlag";
break;
3257 case 'K': flagName =
"KsideFlag";
break;
3258 case '!': flagName =
"BrilliancyFlag";
break;
3259 case '?': flagName =
"BlunderFlag";
break;
3260 case 'U': flagName =
"UserFlag";
break;
3262 if (flagName != NULL) {
3263 Tcl_AppendResult (ti, (flagCount > 0 ?
", " :
" - "),
3269 Tcl_AppendResult (ti,
")</gray>", NULL);
3274 Tcl_AppendResult (ti,
" <red><run ::Bibliography::ShowRef>Bib</run></red>", NULL);
3279 Tcl_AppendResult (ti,
" <blue><run updateTwinChecker>(",
3280 translate (ti,
"twin"),
")</run></blue>", NULL);
3283 sprintf (temp,
"<br><gray><run ::crosstab::Open>%s: %s</run> (%s)</gray><br>",
3287 Tcl_AppendResult (ti, temp, NULL);
3294 uint prevMoveCount = moveCount;
3295 if (toMove ==
WHITE) { prevMoveCount--; }
3298 strcpy(tempTrans, san);
3300 bool printNags =
true;
3304 translate (ti,
"GameStart",
"Start of game") :
3305 translate (ti,
"LineStart",
"Start of line"));
3309 sprintf (temp,
"<run ::move::Back>%u.%s%s</run>",
3310 prevMoveCount, toMove==
WHITE ?
".." :
"", tempTrans);
3313 Tcl_AppendResult (ti,
translate (ti,
"LastMove",
"Last move"), NULL);
3314 Tcl_AppendResult (ti,
": <darkblue>", temp,
"</darkblue>", NULL);
3316 if (printNags && *nags != 0 && !hideNextMove) {
3317 Tcl_AppendResult (ti,
"<red>", NULL);
3318 for (
uint nagCount = 0 ; nags[nagCount] != 0; nagCount++) {
3321 if (nagCount > 0 || (nagstr[0] !=
'!' && nagstr[0] !=
'?')) {
3322 Tcl_AppendResult (ti,
" ", NULL);
3324 Tcl_AppendResult (ti, nagstr, NULL);
3326 Tcl_AppendResult (ti,
"</red>", NULL);
3332 strcpy(tempTrans, san);
3337 translate (ti,
"GameEnd",
"End of game") :
3338 translate (ti,
"LineEnd",
"End of line"));
3341 }
else if (hideNextMove) {
3342 sprintf (temp,
"%u.%s(", moveCount, toMove==
WHITE ?
"" :
"..");
3347 sprintf (temp,
"<run ::move::Forward>%u.%s%s</run>",
3348 moveCount, toMove==
WHITE ?
"" :
"..", tempTrans);
3351 Tcl_AppendResult (ti,
" ",
translate (ti,
"NextMove",
"Next"), NULL);
3352 Tcl_AppendResult (ti,
": <darkblue>", temp,
"</darkblue>", NULL);
3354 if (printNags && !hideNextMove && *nags != 0) {
3355 Tcl_AppendResult (ti,
"<red>", NULL);
3356 for (
uint nagCount = 0 ; nags[nagCount] != 0; nagCount++) {
3359 if (nagCount > 0 || (nagstr[0] !=
'!' && nagstr[0] !=
'?')) {
3360 Tcl_AppendResult (ti,
" ", NULL);
3362 Tcl_AppendResult (ti, nagstr, NULL);
3364 Tcl_AppendResult (ti,
"</red>", NULL);
3368 Tcl_AppendResult (ti,
" <green><run sc_var exit; updateBoard -animate>",
3369 "(<lt>-Var)",
"</run></green>", NULL);
3372 if (showMaterialValue) {
3375 sprintf (temp,
" <gray>(%u-%u", mWhite, mBlack);
3376 Tcl_AppendResult (ti, temp, NULL);
3377 if (mWhite > mBlack) {
3378 sprintf (temp,
":+%u", mWhite - mBlack);
3379 Tcl_AppendResult (ti, temp, NULL);
3380 }
else if (mBlack > mWhite) {
3381 sprintf (temp,
":-%u", mBlack - mWhite);
3382 Tcl_AppendResult (ti, temp, NULL);
3384 Tcl_AppendResult (ti,
")</gray>", NULL);
3390 if (!hideNextMove && varCount > 0) {
3391 Tcl_AppendResult (ti,
"<br>",
translate (ti,
"Variations"),
":", NULL);
3392 for (
uint vnum = 0; vnum < varCount && vnum < 5; vnum++) {
3396 strcpy(tempTrans, s);
3398 sprintf (temp,
" <run sc_var enter %u; updateBoard -animate>v%u",
3400 Tcl_AppendResult (ti,
"<green>", temp,
"</green>: ", NULL);
3402 sprintf (temp,
"<darkblue>(empty)</darkblue>");
3404 sprintf (temp,
"<darkblue>%u.%s%s</darkblue>",
3405 moveCount, toMove ==
WHITE ?
"" :
"..", tempTrans);
3407 Tcl_AppendResult (ti, temp, NULL);
3411 Tcl_AppendResult (ti,
"<red>", s,
"</red>", NULL);
3413 Tcl_AppendResult (ti,
"</run>", NULL);
3421 Tcl_AppendResult (ti,
"<br>",
translate(ti,
"Comment"),
3422 " <green><run makeCommentWin>", NULL);
3425 const char * s = str;
3430 for (len = 0; len < commentWidth; len++, s++) {
3432 if (ch == 0) {
break; }
3435 if (lines >= commentHeight) {
break; }
3436 Tcl_AppendResult (ti,
"<br>", NULL);
3437 }
else if (ch ==
'<') {
3438 Tcl_AppendResult (ti,
"<lt>", NULL);
3439 }
else if (ch ==
'>') {
3440 Tcl_AppendResult (ti,
"<gt>", NULL);
3446 if (len == commentWidth) {
3448 while (ch !=
' ' && ch !=
'\n' && ch != 0) {
3454 Tcl_AppendResult (ti,
"...", NULL);
3457 Tcl_AppendResult (ti,
"</run></green>", NULL);
3459 my_Tcl_Free((
char*) str);
3467 if (!hideNextMove) {
3470 Tcl_AppendResult (ti,
"<br>TB: <blue><run ::tb::open>",
3471 tbStr->
Data(),
"</run></blue>", NULL);
3480 std::string ecoComment(ecoStr.first, ecoStr.second);
3485 if (len >= 4) { estr[3] = 0; }
3488 Tcl_AppendResult (ti,
"<br>ECO: <blue><run ::windows::eco::Refresh ",
3489 estr,
">", tempDStr.
Data(),
3490 "</run></blue>", NULL);
3494 char boardStr [200];
3496 Tcl_AppendResult (ti,
"<br><gray>", boardStr,
"</gray>", NULL);
3511 return errorResult (ti,
"Usage: sc_game load <gameNumber>");
3519 if (gnum < 1 || gnum > db->
numGames()) {
3525 const char * corruptMsg =
"Sorry, this game appears to be corrupt.";
3555 const char * usage =
"Usage: sc_game merge <baseNum> <gameNum> [<endPly>]";
3556 if (argc < 4 || argc > 5) {
return errorResult (ti, usage); }
3565 if (gnum < 1 || gnum > base->
numGames()) {
3572 if (base == db && (
int)gnum == db->
gameNumber) {
3573 return errorResult (ti,
"This game cannot be merged into itself.");
3576 return errorResult (ti,
"The current game has no moves.");
3579 return errorResult (ti,
"The current game has a non-standard start position.");
3588 Game * merge = scratchGame;
3595 return errorResult (ti,
"The merge game has a non-standard start position.");
3600 typedef char compactBoardStr [36];
3601 compactBoardStr * mergeBoards =
new compactBoardStr [nMergePos];
3603 for (
uint i=0; i < nMergePos; i++) {
3618 compactBoardStr currentBoard;
3620 for (
uint n=0; n < nMergePos; n++) {
3621 if (
strEqual (currentBoard, mergeBoards[n])) {
3628 delete [] mergeBoards;
3652 while (ply < endPly) {
3655 if (mergeMove == NULL) {
break; }
3663 if (ply < merge->GetNumHalfMoves()) {
3668 if (elo > 0) { dstr->
Append (
" (", elo,
")"); }
3672 if (elo > 0) { dstr->
Append (
" (", elo,
")"); }
3694 bool sanFormat =
true;
3695 bool printMoves =
true;
3696 bool listFormat =
false;
3697 const uint MAXMOVES = 500;
3701 for (
int arg = 2; arg < argc; arg++) {
3702 if (argv[arg][0] ==
'c') { sanFormat =
false; }
3703 if (argv[arg][0] ==
'n') { printMoves =
false; }
3704 if (argv[arg][0] ==
'l') { printMoves =
false; }
3715 if (sm == NULL) {
break; }
3716 char * s = moveStrings[plyCount];
3730 if (plyCount == MAXMOVES) {
3733 delete[] moveStrings;
3739 for (
uint i = plyCount; i > 0; i--, count++) {
3743 if (printMoves && (count % 2 == 0)) {
3744 sprintf (move,
"%u.", (count / 2) + 1);
3748 strCopy (move, moveStrings [i - 1]);
3751 Tcl_AppendElement (ti, move);
3753 Tcl_AppendResult (ti, (count == 0 ?
"" :
" "), move, NULL);
3756 delete[] moveStrings;
3781 const char * usage =
3782 "Usage: sc_game novelty [-older] base";
3784 bool olderGamesOnly =
false;
3788 && argv[baseArg][0] ==
'-' && argv[baseArg][1] ==
'o' 3790 olderGamesOnly =
true;
3793 if (argc < baseArg || argc > baseArg+1)
return errorResult(ti, usage);
3811 std::string filtername = base->
newFilter();
3818 if (filter.
get(i) == 0)
continue;
3821 if (olderGamesOnly) {
3824 if (count++ != 0)
break;
3861 sc_game_pgn (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
3863 static const char * options [] = {
3864 "-column",
"-comments",
"-base",
"-gameNumber",
"-format",
3865 "-shortHeader",
"-indentComments",
"-indentVariations",
3866 "-symbols",
"-tags",
"-variations",
"-width",
"-space",
3867 "-markCodes",
"-unicode",
3871 OPT_COLUMN, OPT_COMMENTS, OPT_BASE, OPT_GAME_NUMBER, OPT_FORMAT,
3872 OPT_SHORT_HDR, OPT_INDENT_COMMENTS, OPT_INDENT_VARS,
3873 OPT_SYMBOLS, OPT_TAGS, OPT_VARS, OPT_WIDTH, OPT_SPACE,
3874 OPT_NOMARKS, OPT_UNICODE,
3879 uint lineWidth = 99999;
3889 while (thisArg < argc) {
3892 Tcl_AppendResult (ti,
"Invalid option to sc_game pgn: ",
3893 argv[thisArg],
"; valid options are: ", NULL);
3894 for (
const char ** s = options; *s != NULL; s++) {
3895 Tcl_AppendResult (ti, *s,
" ", NULL);
3901 if (thisArg+1 == argc) {
3902 Tcl_AppendResult (ti,
"Invalid option value: sc_game pgn ",
3903 options[index],
" requires a value.", NULL);
3909 if (index == OPT_WIDTH) {
3912 }
else if (index == OPT_BASE) {
3917 }
else if (index == OPT_GAME_NUMBER) {
3922 if (value < 1 || value > base->
numGames()) {
3923 return setResult (ti,
"Invalid game number");
3927 return errorResult (ti,
"Error: empty game file record.");
3930 return errorResult (ti,
"Error reading game file.");
3937 }
else if (index == OPT_FORMAT) {
3940 return errorResult (ti,
"Invalid -format option.");
3961 case OPT_INDENT_VARS:
3963 case OPT_INDENT_COMMENTS:
3983 std::pair<const char*, unsigned> pgnBuf = g->
WriteToPGN(lineWidth);
3984 Tcl_AppendResult (ti, pgnBuf.first, NULL);
4016 if ( argc > 2 && !strcmp( argv[2],
"copy" ) ) {
4019 else if ( argc > 2 && !strcmp( argv[2],
"copyfast" ) ) {
4046 if (dbase == 0)
return errorResult (ti,
"Invalid database number.");
4047 }
else if (argc != 3) {
4048 return errorResult (ti,
"Usage: sc_game save <gameNumber> [targetbaseId]");
4061 ieOld->
GetFlagStr(buf,
"WBMENPTKQ!?U123456");
4090 }
else if (argc != 3) {
4091 return errorResult (ti,
"Usage: sc_game startBoard <fenString>");
4093 const char * str = argv[2];
4101 if (scratchPos.
Random (str+7) !=
OK) {
4102 return errorResult (ti,
"Invalid material string.");
4119 if (argc == 3 && !strcmp(
"variations", argv[2])) {
4121 }
else if (argc == 3 && !strcmp(
"comments", argv[2])) {
4124 return errorResult(ti,
"Usage: sc_game strip [comments|variations]");
4138 const char * usage =
"Usage: sc_game summary [-base <baseNum>] [-gameNumber <gameNum>] header|boards|moves";
4140 const char * options[] = {
4141 "-base",
"-gameNumber", NULL
4143 enum { OPT_BASE, OPT_GNUM };
4149 while (arg+1 < argc) {
4150 const char * value = argv[arg+1];
4154 if (index == OPT_BASE) {
4157 }
else if (index == OPT_GNUM) {
4163 if (arg+1 != argc) {
return errorResult (ti, usage); }
4165 enum modeT { MODE_HEADER, MODE_BOARDS, MODE_MOVES };
4166 modeT mode = MODE_HEADER;
4167 switch (tolower(argv[arg][0])) {
4168 case 'h': mode = MODE_HEADER;
break;
4169 case 'b': mode = MODE_BOARDS;
break;
4170 case 'm': mode = MODE_MOVES;
break;
4174 Game * g = scratchGame;
4179 if (! base->
inUse) {
4180 return errorResult (ti,
"This database is not in use.");
4198 if (mode == MODE_HEADER) {
4202 if (elo > 0) { dstr->
Append (
" (", elo,
")"); }
4205 if (elo > 0) { dstr->
Append (
" (", elo,
")"); }
4209 dstr->
Append (
" (", round,
")");
4215 if (dateStr[4] ==
'.' && dateStr[5] ==
'?') { dateStr[4] = 0; }
4216 if (dateStr[7] ==
'.' && dateStr[8] ==
'?') { dateStr[7] = 0; }
4217 dstr->
Append (dateStr,
" ");
4223 dstr->
Append (
" ", ecoStr);
4225 Tcl_AppendResult (ti, dstr->
Data(), NULL);
4234 if (mode == MODE_BOARDS) {
4237 Tcl_AppendElement (ti, boardStr);
4245 if (toMove ==
WHITE) {
4246 sprintf (temp,
"%u.%s", moveCount, san);
4252 for (
uint nagCount = 0 ; nags[nagCount] != 0; nagCount++) {
4257 (nagstr[0] !=
'!' && nagstr[0] !=
'?')) {
4263 Tcl_AppendElement (ti, temp);
4280 sc_game_tags (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
4282 const char * options[] = {
4283 "get",
"set",
"reload",
"share", NULL
4285 enum { OPT_GET, OPT_SET, OPT_RELOAD, OPT_SHARE };
4313 static const char * options [] = {
4314 "Event",
"Site",
"Date",
"Year",
"Month",
"Day",
4315 "Round",
"White",
"Black",
"Result",
"WhiteElo",
4316 "BlackElo",
"WhiteRType",
"BlackRType",
"ECO",
4317 "EDate",
"EYear",
"EMonth",
"EDay",
"Extra",
4321 T_Event, T_Site, T_Date, T_Year, T_Month, T_Day,
4322 T_Round, T_White, T_Black, T_Result, T_WhiteElo,
4323 T_BlackElo, T_WhiteRType, T_BlackRType, T_ECO,
4324 T_EDate, T_EYear, T_EMonth, T_EDay, T_Extra
4327 const char * usage =
"Usage: sc_game tags get [-last] <tagName>";
4328 const char * tagName;
4331 if (argc < 4 || argc > 5) {
4342 return errorResult (ti,
"Error reading game file.");
4356 Tcl_AppendResult (ti, s, NULL);
4361 Tcl_AppendResult (ti, s, NULL);
4368 Tcl_AppendResult (ti, dateStr, NULL);
4383 Tcl_AppendResult (ti, s, NULL);
4388 Tcl_AppendResult (ti, s, NULL);
4393 Tcl_AppendResult (ti, s, NULL);
4415 Tcl_AppendResult (ti, ecoStr, NULL);
4423 Tcl_AppendResult (ti, dateStr, NULL);
4438 Tcl_AppendResult(ti, tag.first.c_str(),
" \"", tag.second.c_str(),
"\"\n", NULL);
4460 const char * options[] = {
4461 "-event",
"-site",
"-date",
"-round",
"-white",
"-black",
"-result",
4462 "-whiteElo",
"-whiteRatingType",
"-blackElo",
"-blackRatingType",
4463 "-eco",
"-eventdate",
"-extra",
4467 T_EVENT, T_SITE, T_DATE, T_ROUND, T_WHITE, T_BLACK, T_RESULT,
4468 T_WHITE_ELO, T_WHITE_RTYPE, T_BLACK_ELO, T_BLACK_RTYPE,
4469 T_ECO, T_EVENTDATE, T_EXTRA
4473 if (((argc-arg) % 2) != 0) {
4474 return errorResult (ti,
"Odd number of parameters.");
4478 while (arg+1 < argc) {
4480 const char * value = argv[arg+1];
4511 const char ** largv;
4512 if (Tcl_SplitList (ti, value, &largc,
4513 (CONST84
char ***) &largv) != TCL_OK) {
4515 return errorResult (ti,
"Error parsing extra tags.");
4519 for (
int i=0; i < largc; i++) {
4521 char valueStr [1024];
4525 if (sscanf (largv[i],
"%s \"%[^\"]\"\n", tagStr, valueStr) == 2) {
4531 Tcl_Free ((
char *) largv);
4574 const char * usage =
4575 "Usage: sc_game tags share [check|update] <gameNumber1> <gameNumber2>";
4576 if (argc != 6) {
return errorResult (ti, usage); }
4577 bool updateMode =
false;
4588 if (gn1 == 0) {
return TCL_OK; }
4589 if (gn2 == 0) {
return TCL_OK; }
4590 if (gn1 == gn2) {
return TCL_OK; }
4591 if (gn1 > db->
numGames()) {
return TCL_OK; }
4592 if (gn2 > db->
numGames()) {
return TCL_OK; }
4600 bool updated1 =
false;
4601 bool updated2 =
false;
4612 if (date1 == 0) { *dateStr1 = 0; }
4613 if (date2 == 0) { *dateStr2 = 0; }
4622 Tcl_AppendElement (ti,
"Date");
4623 Tcl_AppendElement (ti, dateStr1);
4624 Tcl_AppendElement (ti, dateStr2);
4634 Tcl_AppendElement (ti,
"Date");
4635 Tcl_AppendElement (ti, dateStr2);
4636 Tcl_AppendElement (ti, dateStr1);
4647 if (event1empty && !event2empty) {
4654 Tcl_AppendElement (ti,
"Event");
4655 Tcl_AppendElement (ti, eventStr1);
4656 Tcl_AppendElement (ti, eventStr2);
4659 if (event2empty && !event1empty) {
4666 Tcl_AppendElement (ti,
"Event");
4667 Tcl_AppendElement (ti, eventStr2);
4668 Tcl_AppendElement (ti, eventStr1);
4679 if (round1empty && !round2empty) {
4686 Tcl_AppendElement (ti,
"Round");
4687 Tcl_AppendElement (ti, roundStr1);
4688 Tcl_AppendElement (ti, roundStr2);
4691 if (round2empty && !round1empty) {
4698 Tcl_AppendElement (ti,
"Round");
4699 Tcl_AppendElement (ti, roundStr2);
4700 Tcl_AppendElement (ti, roundStr1);
4709 if (welo1 == 0 && welo2 != 0) {
4716 Tcl_AppendElement (ti,
"WhiteElo");
4721 if (welo2 == 0 && welo1 != 0) {
4728 Tcl_AppendElement (ti,
"WhiteElo");
4733 if (belo1 == 0 && belo2 != 0) {
4740 Tcl_AppendElement (ti,
"BlackElo");
4745 if (belo2 == 0 && belo1 != 0) {
4752 Tcl_AppendElement (ti,
"BlackElo");
4759 if (updateMode && (updated1 || updated2)) {
4775 date_ValidString (
const char * str)
4780 for (
uint i=0; i < 3; i++) {
4781 uint maxValue = maxValues[i];
4782 bool seenQuestion, seenDigit, seenOther;
4783 seenQuestion = seenDigit = seenOther =
false;
4784 const char *
start = str;
4785 while (*str != 0 && *str !=
'.') {
4787 if (ch >=
'0' && ch <=
'9') {
4789 }
else if (ch ==
'?') {
4790 seenQuestion =
true;
4797 if (seenOther) {
return false; }
4798 if (seenQuestion && seenDigit) {
return false; }
4802 if (value > maxValue) {
return false; }
4804 if (*str == 0) {
return true; }
else { str++; }
4813 sc_info (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
4815 static const char * options [] = {
4816 "clipbase",
"decimal",
"priority",
4817 "html",
"limit",
"ratings",
4818 "suffix",
"tb",
"validDate",
"version",
"language", NULL
4821 INFO_CLIPBASE, INFO_DECIMAL, INFO_PRIORITY,
4822 INFO_HTML, INFO_LIMIT, INFO_RATINGS,
4823 INFO_SUFFIX, INFO_TB, INFO_VALIDDATE, INFO_VERSION, INFO_LANGUAGE
4835 decimalPointChar = argv[2][0];
4837 return UI_Result(ti,
OK, std::string(1, decimalPointChar));
4871 case INFO_VALIDDATE:
4873 return errorResult (ti,
"Usage: sc_info validDate <datestring>");
4875 return UI_Result(ti,
OK, date_ValidString (argv[2]));
4886 return errorResult (ti,
"Usage: sc_info language <lang>");
4888 if ( strcmp(argv[2],
"en") == 0) {
language = 0;}
4889 if ( strcmp(argv[2],
"fr") == 0) {
language = 1;}
4890 if ( strcmp(argv[2],
"es") == 0) {
language = 2;}
4891 if ( strcmp(argv[2],
"de") == 0) {
language = 3;}
4892 if ( strcmp(argv[2],
"it") == 0) {
language = 4;}
4893 if ( strcmp(argv[2],
"ne") == 0) {
language = 5;}
4894 if ( strcmp(argv[2],
"cz") == 0) {
language = 6;}
4895 if ( strcmp(argv[2],
"hu") == 0) {
language = 7;}
4896 if ( strcmp(argv[2],
"no") == 0) {
language = 8;}
4897 if ( strcmp(argv[2],
"sw") == 0) {
language = 9;}
4898 if ( strcmp(argv[2],
"ca") == 0) {
language = 10;}
4899 if ( strcmp(argv[2],
"fi") == 0) {
language = 11;}
4900 if ( strcmp(argv[2],
"gr") == 0) {
language = 12;}
4916 static const char * options [] = {
4917 "elo",
"year",
"bases", NULL
4920 LIM_ELO, LIM_YEAR, LIM_BASES
4954 static const char * options [] = {
4964 const char * suffix =
"";
4980 sc_info_tb (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
4982 const char * usage =
4983 "Usage: sc_info tb [<directory>|available <material>|cache <size-kb>]";
4990 }
else if (argc == 3) {
4997 }
else if (argc == 4 && argv[2][0] ==
'a') {
5003 if (toupper(*material) !=
'K') {
return UI_Result(ti,
OK,
false); }
5007 char ch = toupper(*material);
5009 if (ch == 0) {
break; }
5010 if (ch ==
'K') { side =
BLACK;
continue; }
5013 if (p ==
EMPTY) {
continue; }
5018 }
else if (argc == 4 && argv[2][0] ==
'c') {
5033 sc_move (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
5035 static const char * options [] = {
5036 "add",
"addSan",
"addUCI",
"back",
"end",
"forward",
5037 "pgn",
"ply",
"start", NULL
5040 MOVE_ADD, MOVE_ADDSAN, MOVE_ADDUCI, MOVE_BACK, MOVE_END, MOVE_FORWARD,
5041 MOVE_PGN, MOVE_PLY, MOVE_START
5066 }
while (err ==
OK);
5081 return errorResult (ti,
"Usage: sc_move ply <plynumber>");
5098 sc_move_add (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
5102 return errorResult (ti,
"Usage: sc_move add <sq> <sq> <promo>");
5108 if (promo == 0) { promo =
EMPTY; }
5115 if (promo ==
EMPTY) {
5142 for (
int i = 2; i < argc; ++i) {
5159 if (argc < 3) {
return TCL_OK; }
5160 char * ptr = (
char *) argv[2];
5167 if (ptr[4] ==
' ') {
5170 }
else if (ptr[4] == 0) {
5187 Tcl_AppendResult (ti, tmp,
" ", NULL);
5207 int numMovesTakenBack = 0;
5214 for (
int i = 0; i < count; i++) {
5216 numMovesTakenBack++;
5229 int numMovesMade = 0;
5237 for (
int i = 0; i < count; i++) {
5252 sc_move_pgn (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
5255 return errorResult (ti,
"Usage: sc_move pgn <offset>");
5269 sc_pos (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
5271 static const char * options [] = {
5272 "addNag",
"analyze",
"bestSquare",
"board",
"clearNags",
5273 "fen",
"getComment",
"getNags",
"hash",
"html",
5274 "isAt",
"isCheck",
"isLegal",
"isPromotion",
5275 "matchMoves",
"moveNumber",
"pgnOffset",
5276 "probe",
"setComment",
"side",
"tex",
"moves",
"location",
5277 "attacks",
"getPrevComment", NULL
5280 POS_ADDNAG, POS_ANALYZE, POS_BESTSQ, POS_BOARD, POS_CLEARNAGS,
5281 POS_FEN, POS_GETCOMMENT, POS_GETNAGS, POS_HASH, POS_HTML,
5282 POS_ISAT, POS_ISCHECK, POS_ISLEGAL, POS_ISPROMO,
5283 POS_MATCHMOVES, POS_MOVENUM, POS_PGNOFFSET,
5284 POS_PROBE, POS_SETCOMMENT, POS_SIDE, POS_TEX, POS_MOVES, LOCATION,
5285 POS_ATTACKS, POS_GETPREVCOMMENT
5304 Tcl_AppendResult (ti, boardStr, NULL);
5314 Tcl_AppendResult (ti, boardStr, NULL);
5317 case POS_GETCOMMENT:
5318 const char * tempStr;
5321 Tcl_AppendResult (ti, tempStr, NULL);
5325 case POS_GETPREVCOMMENT:
5349 case POS_MATCHMOVES:
5370 case POS_SETCOMMENT:
5375 ?
"white" :
"black");
5381 if (argc > 2 &&
strIsPrefix (argv[2],
"flip")) { flip =
true; }
5384 Tcl_AppendResult (ti, dstr->
Data(), NULL);
5396 for (
uint i = 0; i < pos.GetCount(c); i++) {
5399 int att = pos.TreeCalcAttacks(
color_Flip(c), sq);
5402 if (att > 1) Tcl_AppendElement(ti,
"green");
5403 else if (att > 0) Tcl_AppendElement(ti,
"yellow");
5404 else Tcl_AppendElement(ti,
"red");
5426 return errorResult (ti,
"Usage: sc_pos addNag <nagvalue>");
5428 const char * nagStr = argv[2];
5429 if( strcmp(nagStr,
"X") == 0)
5431 else if( strcmp(nagStr,
"Y") == 0)
5455 const char * usage =
"Usage: sc_pos analyze [<option> <value> ...]";
5457 uint searchTime = 1000;
5458 uint hashTableKB = 1024;
5459 uint pawnTableKB = 32;
5460 bool postMode =
false;
5461 bool pruning =
false;
5463 uint searchdepth = 0;
5465 static const char * options [] = {
5466 "-time",
"-hashkb",
"-pawnkb",
"-post",
"-pruning",
"-mindepth",
"-searchdepth", NULL
5469 OPT_TIME, OPT_HASH, OPT_PAWN, OPT_POST, OPT_PRUNING, OPT_MINDEPTH, OPT_SEARCHDEPTH
5472 while (arg+1 < argc) {
5473 const char * option = argv[arg];
5474 const char * value = argv[arg+1];
5484 case OPT_SEARCHDEPTH: searchdepth =
strGetUnsigned(value);
break;
5489 if (arg != argc) {
return errorResult (ti, usage); }
5502 if (searchdepth > 0)
5507 int score = engine->
Think (&mlist);
5512 if (mlist.
Size() > 0) {
5523 class SelectBySquare {
5527 explicit SelectBySquare(
squareT sq) : sq_(sq) {}
5529 return sm.
from == sq_ || sm.
to == sq_;
5544 return errorResult (ti,
"Usage: sc_pos bestSquare <square>");
5553 if (sqInt >= 0 && sqInt <= 63) { sq = sqInt; }
5556 return errorResult (ti,
"Usage: sc_pos bestSquare <square>");
5566 std::partition(mlist.
begin(), mlist.
end(), SelectBySquare(sq))
5570 if (mlist.
Size() == 0) {
5574 if (mlist.
Size() > 1) {
5584 if (ecoBook != NULL) {
5585 for (
uint i=0; i < mlist.
Size(); i++) {
5587 ecoT eco = ecoBook->findECO(pos);
5589 if (eco >= bestEco) {
5590 secondBestEco = bestEco;
5592 std::rotate(mlist.
begin(), mlist.
begin() + i,
5593 mlist.
begin() + i + 1);
5598 if (bestEco ==
ECO_None || bestEco == secondBestEco) {
5607 engine->
Think (&mlist);
5620 if (sm->
from == sq) { bestSq = sm->
to; }
5639 Tcl_AppendResult (ti, temp,
" ", NULL);
5650 sc_pos_hash (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
5652 const char * usage =
"Usage: sc_pos hash [full|pawn]";
5653 bool pawnHashOnly =
false;
5656 switch (argv[2][0]) {
5657 case 'f': pawnHashOnly =
false;
break;
5658 case 'p': pawnHashOnly =
true;
break;
5679 sc_pos_html (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
5681 const char * usage =
"Usage: sc_pos html [-flip <boolean>] [-path <path>] [<style:0|1>]";
5682 uint style = htmlDiagStyle;
5685 const char * path = NULL;
5687 if (argc > arg+1 &&
strEqual (argv[arg],
"-flip")) {
5691 if (argc > arg+1 &&
strEqual (argv[arg],
"-path")) {
5695 if (argc < arg || argc > arg+1) {
5702 Tcl_AppendResult (ti, dstr->
Data(), NULL);
5714 sc_pos_isAt (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
5716 static const char * options [] = {
5717 "start",
"end",
"vstart",
"vend", NULL
5720 OPT_START, OPT_END, OPT_VSTART, OPT_VEND
5739 return errorResult (ti,
"Usage: sc_pos isAt start|end|vstart|vend");
5752 return errorResult (ti,
"Usage: sc_move isPromo <square> <square>");
5759 if (fromSq < A1 || fromSq >
H8 || toSq < A1 || toSq >
H8) {
5760 return errorResult (ti,
"Usage: sc_move isPromo <square> <square>");
5773 return errorResult (ti,
"Usage: sc_pos isLegal <square> <square>");
5779 if (sq1 < 0 || sq1 > 63 || sq2 < 0 || sq2 > 63) {
5788 bool found = mlist.
begin() !=
5789 std::partition(mlist.
begin(), end1, SelectBySquare(sq2));
5803 if (argc != 3 && argc != 4) {
5804 return errorResult (ti,
"Usage: sc_pos matchMoves <movetext-prefix>");
5806 bool coordMoves =
false;
5807 const char * prefix = argv[2];
5814 for (
uint i=0; i < sanList.
num; i++) {
5819 Tcl_AppendElement (ti, str);
5826 if (prefix[0] >=
'a' && prefix[0] <=
'h') {
5828 newPrefix[0] = toupper(newPrefix[0]);
5829 for (
uint i=0; i < sanList.
num; i++) {
5832 Tcl_AppendElement (ti, str);
5836 my_Tcl_Free((
char*) newPrefix);
5844 if (coordMoves && prefix[0] >=
'a' && prefix[0] <=
'h') {
5847 for (
uint i=0; i < mList.
Size(); i++) {
5860 Tcl_AppendElement (ti, str);
5881 for (
uint i=0; i < sanList.
num; i++) {
5882 Tcl_AppendElement (ti, sanList.
list[i]);
5891 sc_pos_probe (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
5893 const char * usage =
"Usage: sc_pos probe [score|report|optimal|board <sq>]";
5894 static const char * options[] = {
5895 "score",
"report",
"optimal",
"board", NULL
5897 enum { OPT_SCORE, OPT_REPORT, OPT_OPTIMAL, OPT_BOARD };
5899 int option = OPT_SCORE;
5904 if (option == OPT_REPORT) {
5905 if (argc != 3) {
return errorResult (ti, usage); }
5910 Tcl_AppendResult (ti, tbReport->
Data(), NULL);
5913 }
else if (option == OPT_OPTIMAL) {
5914 if (argc != 3) {
return errorResult (ti, usage); }
5919 Tcl_AppendResult (ti, tbOptimal->
Data(), NULL);
5922 }
else if (option == OPT_SCORE) {
5927 }
else if (option == OPT_BOARD) {
5942 const char * usage =
"Usage: sc_pos probe board <square>";
5944 if (argc != 4) {
return errorResult (ti, usage); }
5950 if (sqInt >= 0 && sqInt <= 63) { sq = sqInt; }
5959 if (board[sq] ==
EMPTY) {
return TCL_OK; }
5962 const char * result =
"";
5972 }
else if (score < 0) {
5980 Tcl_AppendResult (ti, result, NULL);
5992 return errorResult (ti,
"Usage: sc_pos setComment <comment-text>");
5994 const char * str = argv[2];
5997 if (str[0] == 0 || (isspace((
char)str[0]) && str[1] == 0)) {
5999 if (oldComment != NULL) {
6005 if (oldComment == NULL || !
strEqual (str, oldComment)) {
6028 "Usage: sc_name correct p|e|s|r <corrections>");
6031 const char * str = argv[3];
6037 uint errorCount = 0;
6038 uint correctionCount = 0;
6039 uint badDateCount = 0;
6043 std::vector<idNumberT> oldIDs;
6044 std::vector<std::string> newNames;
6045 std::vector<std::pair<dateT, dateT> > dates(nb->
GetNumNames(nt),
6049 while (*str != 0 && *str !=
'\n') {
6050 if (length < 511) { line[length++] = *str; }
6054 if (*str ==
'\n') { str++; }
6058 if (*s !=
'"') {
continue; }
6062 if (sscanf (line,
"\"%[^\"]\" >> \"%[^\"]\" (%d) %[0-9.?]--%[0-9.?]",
6063 oldName, newName, &dummyCount, birth, death) < 2) {
6076 oldIDs.emplace_back(oldID);
6077 newNames.emplace_back(newName);
6082 std::vector<idNumberT> newIDs;
6083 auto initNewIDs = [&](
const std::vector<idNumberT>& v_ids) {
6085 std::iota(newIDs.begin(), newIDs.end(),
idNumberT(0));
6086 auto it = v_ids.begin();
6087 for (
auto&
id : oldIDs) {
6094 auto newID = newIDs[oldID];
6100 auto range = dates[oldID];
6101 if (date < range.first ||
6102 (range.second !=
ZERO_DATE && date > range.second)) {
6113 newNames, initNewIDs, entry_op);
6121 return UI_Result(ti, changes.first, res);
6137 const char * usage =
"Usage: sc_name edit <type> <oldName> <newName>";
6138 const char * options[] = {
6139 "player",
"event",
"site",
"round",
"rating",
6140 "date",
"edate", NULL
6143 OPT_PLAYER, OPT_EVENT, OPT_SITE, OPT_ROUND, OPT_RATING,
6144 OPT_DATE, OPT_EVENTDATE
6157 case OPT_RATING:
break;
6158 case OPT_DATE:
break;
6159 case OPT_EVENTDATE:
break;
6164 if (option == OPT_RATING) {
6165 if (argc != 7) {
return errorResult (ti, usage); }
6167 if (argc != 6) {
return errorResult (ti, usage); }
6170 enum { EDIT_ALL, EDIT_FILTER, EDIT_CTABLE };
6171 int editSelection = EDIT_ALL;
6172 switch (argv[3][0]) {
6173 case 'a': editSelection = EDIT_ALL;
break;
6174 case 'f': editSelection = EDIT_FILTER;
break;
6175 case 'c': editSelection = EDIT_CTABLE;
break;
6180 const char * oldName = argv[4];
6181 const char * newName = argv[5];
6185 byte newRatingType = 0;
6186 if (option == OPT_RATING) {
6190 if (option == OPT_DATE || option == OPT_EVENTDATE) {
6198 if (option != OPT_DATE && option != OPT_EVENTDATE) {
6205 dateT eventDate = 0;
6206 if (editSelection == EDIT_CTABLE) {
6216 if (editSelection != EDIT_CTABLE)
6218 return isCrosstableGame(&ie, siteId, eventId, eventDate);
6221 std::string filter =
6222 (editSelection == EDIT_FILTER) ?
"dbfilter" : dbase->
newFilter();
6225 std::pair<errorT, size_t> changes;
6229 if (ie.
GetDate() == oldDate && inCTable(ie)) {
6248 bool bTB = inCTable(ie);
6249 bool bWH = (ie.
GetWhite() == oldID);
6250 bool bBK = (ie.
GetBlack() == oldID);
6251 if (bTB && (bWH || bBK)) {
6268 nt, hf, prg, std::vector<std::string>(1, newName),
6269 [&](
const std::vector<idNumberT>& v) {
6273 return (
id == oldID && inCTable(ie)) ? newID :
id;
6277 if (editSelection != EDIT_FILTER)
6280 return UI_Result(ti, changes.first, changes.second);
6287 const char * usageStr =
"Usage: sc_name retrievename <player>";
6288 if (argc != 3 ) {
return errorResult (ti, usageStr); }
6290 return UI_Result(ti,
OK, (res.size() == 1) ? res[0] :
"");
6297 const char** argv) {
6298 auto usage =
"Usage: sc_name elo [year] <player>";
6299 if (argc < 3 || argc > 4)
6302 const char* playerName = argv[argc - 1];
6308 for (
uint month = 1; month < 13; month++) {
6311 sprintf(temp,
"%4u.%02u", year, (month - 1) * 100 / 12);
6313 sprintf(temp,
"%4u", elo);
6329 static char * lastPlayerName = NULL;
6330 const char * usageStr =
"Usage: sc_name info [-htext] <player>";
6332 if (argc != 3 && argc != 4) {
return errorResult (ti, usageStr); }
6334 bool htextOutput =
false;
6335 bool setFilter =
false;
6336 bool setOpponent =
false;
6339 {
false,
false,
false,
false },
6340 {
false,
false,
false,
false }
6344 const char * opt = argv[2];
6347 }
else if (opt[0] ==
'-' && (opt[1] ==
'f' || opt[1] ==
'o')) {
6348 if (opt[1] ==
'f') {
6355 const char * fopt = opt + 2;
6356 while (*fopt != 0) {
6399 const char * playerName = argv[argc-1];
6401 if (lastPlayerName != NULL) { playerName = lastPlayerName; }
6403 if (lastPlayerName != NULL) {
delete[] lastPlayerName; }
6410 Tcl_AppendResult (ti,
"The name \"", playerName,
6411 "\" does not exist in this database.", NULL);
6417 const char * opponent = NULL;
6424 if (opponent != NULL) {
6430 enum {STATS_ALL = 0, STATS_FILTER, STATS_OPP};
6435 uint whitecount[3] = {0};
6436 uint blackcount[3] = {0};
6437 uint totalcount[3] = {0};
6438 for (
uint stat=STATS_ALL; stat <= STATS_OPP; stat++) {
6440 whitescore[stat][r] = 0;
6441 blackscore[stat][r] = 0;
6442 bothscore[stat][r] = 0;
6448 for (
uint ecoGroup=0; ecoGroup < 50; ecoGroup++) {
6449 ecoCount[
WHITE][ecoGroup] = ecoCount[
BLACK][ecoGroup] = 0;
6450 ecoScore[
WHITE][ecoGroup] = ecoScore[
BLACK][ecoGroup] = 0;
6465 if (ecoStr[0] != 0) {
6466 ecoClass = ((ecoStr[0] -
'A') * 10) + (ecoStr[1] -
'0');
6467 if (ecoClass < 0 || ecoClass >= 50) { ecoClass = -1; }
6477 if (whiteId ==
id) {
6479 if (ecoClass >= 0) {
6480 ecoCount[
WHITE][ecoClass]++;
6483 whitescore[STATS_ALL][result]++;
6484 bothscore[STATS_ALL][result]++;
6485 whitecount[STATS_ALL]++;
6486 totalcount[STATS_ALL]++;
6488 whitescore[STATS_FILTER][result]++;
6489 bothscore[STATS_FILTER][result]++;
6490 whitecount[STATS_FILTER]++;
6491 totalcount[STATS_FILTER]++;
6493 if (opponent != NULL && blackId == opponentId) {
6494 whitescore[STATS_OPP][result]++;
6495 bothscore[STATS_OPP][result]++;
6496 whitecount[STATS_OPP]++;
6497 totalcount[STATS_OPP]++;
6498 if (setOpponent && filter[
WHITE][result]) {
6502 if (setFilter && filter[
WHITE][result]) {
6505 }
else if (blackId ==
id) {
6508 if (ecoClass >= 0) {
6509 ecoCount[
BLACK][ecoClass]++;
6512 blackscore[STATS_ALL][result]++;
6513 bothscore[STATS_ALL][result]++;
6514 blackcount[STATS_ALL]++;
6515 totalcount[STATS_ALL]++;
6517 blackscore[STATS_FILTER][result]++;
6518 bothscore[STATS_FILTER][result]++;
6519 blackcount[STATS_FILTER]++;
6520 totalcount[STATS_FILTER]++;
6522 if (opponent != NULL && whiteId == opponentId) {
6523 blackscore[STATS_OPP][result]++;
6524 bothscore[STATS_OPP][result]++;
6525 blackcount[STATS_OPP]++;
6526 totalcount[STATS_OPP]++;
6527 if (setOpponent && filter[
BLACK][result]) {
6531 if (setFilter && filter[
BLACK][result]) {
6538 if (firstGameDate ==
ZERO_DATE || date < firstGameDate) {
6539 firstGameDate =
date;
6541 if (lastGameDate ==
ZERO_DATE || date > lastGameDate) {
6542 lastGameDate =
date;
6548 uint score, percent;
6550 const char * newline = (htextOutput ?
"<br>" :
"\n");
6551 const char * startHeading = (htextOutput ?
"<darkblue>" :
"");
6552 const char * endHeading = (htextOutput ?
"</darkblue>" :
"");
6553 const char * startBold = (htextOutput ?
"<b>" :
"");
6554 const char * endBold = (htextOutput ?
"</b>" :
"");
6558 uint wbtWidth = wWidth;
6559 if (bWidth > wbtWidth) { wbtWidth = bWidth; }
6560 if (tWidth > wbtWidth) { wbtWidth = tWidth; }
6561 const char * fmt = \
6562 "%s %-*s %3u%c%02u%% +%s%3u%s =%s%3u%s -%s%3u%s %4u%c%c /%s%4u%s";
6565 Tcl_AppendResult (ti, startBold, playerName, endBold, newline, NULL);
6568 if (spChecker != NULL) {
6570 if (pInfo) { Tcl_AppendResult (ti,
" ", pInfo->
GetComment(), newline, NULL); }
6572 sprintf (temp,
" %s%u%s %s (%s: %u)",
6573 htextOutput ?
"<red><run sc_name info -faA {}; ::windows::stats::Refresh>" :
"",
6574 totalcount[STATS_ALL],
6575 htextOutput ?
"</run></red>" :
"",
6576 (totalcount[STATS_ALL] == 1 ?
6579 totalcount[STATS_FILTER]);
6580 Tcl_AppendResult (ti, temp, NULL);
6584 Tcl_AppendResult (ti,
", ", temp, NULL);
6586 if (lastGameDate > firstGameDate) {
6589 Tcl_AppendResult (ti,
"--", temp, NULL);
6591 Tcl_AppendResult (ti, newline, NULL);
6594 if (spChecker != NULL) {
6595 std::vector<const char*> bio;
6598 for (
size_t i=0, n=bio.size(); i < n; i++) {
6600 Tcl_AppendResult (ti, newline, startHeading,
6602 endHeading, newline, NULL);
6604 Tcl_AppendResult (ti,
" ", bio[i], newline, NULL);
6612 Tcl_AppendResult (ti, newline, startHeading, temp,
":",
6613 endHeading, newline, NULL);
6615 score = percent = 0;
6616 if (whitecount[STATS_ALL] > 0) {
6620 percent = score * 5000 / whitecount[STATS_ALL];
6623 htextOutput ?
"<tt>" :
"",
6626 percent / 100, decimalPointChar, percent % 100,
6627 htextOutput ?
"<red><run sc_name info -fw {}; ::windows::stats::Refresh>" :
"",
6629 htextOutput ?
"</run></red>" :
"",
6630 htextOutput ?
"<red><run sc_name info -fd {}; ::windows::stats::Refresh>" :
"",
6632 htextOutput ?
"</run></red>" :
"",
6633 htextOutput ?
"<red><run sc_name info -fl {}; ::windows::stats::Refresh>" :
"",
6635 htextOutput ?
"</run></red>" :
"",
6636 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6637 htextOutput ?
"<red><run sc_name info -fa {}; ::windows::stats::Refresh>" :
"",
6638 whitecount[STATS_ALL],
6639 htextOutput ?
"</run></red></tt>" :
"");
6640 Tcl_AppendResult (ti, temp, newline, NULL);
6642 score = percent = 0;
6643 if (blackcount[STATS_ALL] > 0) {
6647 percent = score * 5000 / blackcount[STATS_ALL];
6650 htextOutput ?
"<tt>" :
"",
6653 percent / 100, decimalPointChar, percent % 100,
6654 htextOutput ?
"<red><run sc_name info -fW {}; ::windows::stats::Refresh>" :
"",
6655 blackscore[STATS_ALL][RESULT_White],
6656 htextOutput ?
"</run></red>" :
"",
6657 htextOutput ?
"<red><run sc_name info -fD {}; ::windows::stats::Refresh>" :
"",
6658 blackscore[STATS_ALL][RESULT_Draw],
6659 htextOutput ?
"</run></red>" :
"",
6660 htextOutput ?
"<red><run sc_name info -fL {}; ::windows::stats::Refresh>" :
"",
6661 blackscore[STATS_ALL][RESULT_Black],
6662 htextOutput ?
"</run></red>" :
"",
6663 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6664 htextOutput ?
"<red><run sc_name info -fA {}; ::windows::stats::Refresh>" :
"",
6665 blackcount[STATS_ALL],
6666 htextOutput ?
"</run></red></tt>" :
"");
6667 Tcl_AppendResult (ti, temp, newline, NULL);
6669 score = percent = 0;
6670 if (totalcount[STATS_ALL] > 0) {
6674 percent = score * 5000 / totalcount[STATS_ALL];
6677 htextOutput ?
"<tt>" :
"",
6680 percent / 100, decimalPointChar, percent % 100,
6681 htextOutput ?
"<red><run sc_name info -fwW {}; ::windows::stats::Refresh>" :
"",
6682 bothscore[STATS_ALL][RESULT_White],
6683 htextOutput ?
"</run></red>" :
"",
6684 htextOutput ?
"<red><run sc_name info -fdD {}; ::windows::stats::Refresh>" :
"",
6685 bothscore[STATS_ALL][RESULT_Draw],
6686 htextOutput ?
"</run></red>" :
"",
6687 htextOutput ?
"<red><run sc_name info -flL {}; ::windows::stats::Refresh>" :
"",
6688 bothscore[STATS_ALL][RESULT_Black],
6689 htextOutput ?
"</run></red>" :
"",
6690 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6691 htextOutput ?
"<red><run sc_name info -faA {}; ::windows::stats::Refresh>" :
"",
6692 totalcount[STATS_ALL],
6693 htextOutput ?
"</run></red></tt>" :
"");
6694 Tcl_AppendResult (ti, temp, newline, NULL);
6700 Tcl_AppendResult (ti, newline, startHeading, temp,
":",
6701 endHeading, newline, NULL);
6702 score = percent = 0;
6703 if (whitecount[STATS_FILTER] > 0) {
6707 percent = score * 5000 / whitecount[STATS_FILTER];
6710 htextOutput ?
"<tt>" :
"",
6713 percent / 100, decimalPointChar, percent % 100,
6714 "", whitescore[STATS_FILTER][RESULT_White],
"",
6715 "", whitescore[STATS_FILTER][RESULT_Draw],
"",
6716 "", whitescore[STATS_FILTER][RESULT_Black],
"",
6717 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6718 "", whitecount[STATS_FILTER],
6719 htextOutput ?
"</tt>" :
"");
6720 Tcl_AppendResult (ti, temp, newline, NULL);
6722 score = percent = 0;
6723 if (blackcount[STATS_FILTER] > 0) {
6727 percent = score * 5000 / blackcount[STATS_FILTER];
6730 htextOutput ?
"<tt>" :
"",
6733 percent / 100, decimalPointChar, percent % 100,
6734 "", blackscore[STATS_FILTER][RESULT_White],
"",
6735 "", blackscore[STATS_FILTER][RESULT_Draw],
"",
6736 "", blackscore[STATS_FILTER][RESULT_Black],
"",
6737 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6738 "", blackcount[STATS_FILTER],
6739 htextOutput ?
"</tt>" :
"");
6740 Tcl_AppendResult (ti, temp, newline, NULL);
6742 score = percent = 0;
6743 if (totalcount[STATS_FILTER] > 0) {
6747 percent = score * 5000 / totalcount[STATS_FILTER];
6750 htextOutput ?
"<tt>" :
"",
6753 percent / 100, decimalPointChar, percent % 100,
6754 "", bothscore[STATS_FILTER][RESULT_White],
"",
6755 "", bothscore[STATS_FILTER][RESULT_Draw],
"",
6756 "", bothscore[STATS_FILTER][RESULT_Black],
"",
6757 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6758 "", totalcount[STATS_FILTER],
6759 htextOutput ?
"</tt>" :
"");
6760 Tcl_AppendResult (ti, temp, newline, NULL);
6764 if (opponent != NULL) {
6765 Tcl_AppendResult (ti, newline, startHeading,
6767 startBold, opponent, endBold,
":",
6768 endHeading, newline, NULL);
6770 score = percent = 0;
6771 if (whitecount[STATS_OPP] > 0) {
6775 percent = score * 5000 / whitecount[STATS_OPP];
6778 htextOutput ?
"<tt>" :
"",
6781 percent / 100, decimalPointChar, percent % 100,
6782 htextOutput ?
"<red><run sc_name info -ow {}; ::windows::stats::Refresh>" :
"",
6783 whitescore[STATS_OPP][RESULT_White],
6784 htextOutput ?
"</run></red>" :
"",
6785 htextOutput ?
"<red><run sc_name info -od {}; ::windows::stats::Refresh>" :
"",
6786 whitescore[STATS_OPP][RESULT_Draw],
6787 htextOutput ?
"</run></red>" :
"",
6788 htextOutput ?
"<red><run sc_name info -ol {}; ::windows::stats::Refresh>" :
"",
6789 whitescore[STATS_OPP][RESULT_Black],
6790 htextOutput ?
"</run></red>" :
"",
6791 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6792 htextOutput ?
"<red><run sc_name info -oa {}; ::windows::stats::Refresh>" :
"",
6793 whitecount[STATS_OPP],
6794 htextOutput ?
"</run></red></tt>" :
"");
6795 Tcl_AppendResult (ti, temp, newline, NULL);
6797 score = percent = 0;
6798 if (blackcount[STATS_OPP] > 0) {
6802 percent = score * 5000 / blackcount[STATS_OPP];
6805 htextOutput ?
"<tt>" :
"",
6808 percent / 100, decimalPointChar, percent % 100,
6809 htextOutput ?
"<red><run sc_name info -oW {}; ::windows::stats::Refresh>" :
"",
6810 blackscore[STATS_OPP][RESULT_White],
6811 htextOutput ?
"</run></red>" :
"",
6812 htextOutput ?
"<red><run sc_name info -oD {}; ::windows::stats::Refresh>" :
"",
6813 blackscore[STATS_OPP][RESULT_Draw],
6814 htextOutput ?
"</run></red>" :
"",
6815 htextOutput ?
"<red><run sc_name info -oL {}; ::windows::stats::Refresh>" :
"",
6816 blackscore[STATS_OPP][RESULT_Black],
6817 htextOutput ?
"</run></red>" :
"",
6818 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6819 htextOutput ?
"<red><run sc_name info -oA {}; ::windows::stats::Refresh>" :
"",
6820 blackcount[STATS_OPP],
6821 htextOutput ?
"</run></red></tt>" :
"");
6822 Tcl_AppendResult (ti, temp, newline, NULL);
6824 score = percent = 0;
6825 if (totalcount[STATS_OPP] > 0) {
6829 percent = score * 5000 / totalcount[STATS_OPP];
6832 htextOutput ?
"<tt>" :
"",
6835 percent / 100, decimalPointChar, percent % 100,
6836 htextOutput ?
"<red><run sc_name info -owW {}; ::windows::stats::Refresh>" :
"",
6837 bothscore[STATS_OPP][RESULT_White],
6838 htextOutput ?
"</run></red>" :
"",
6839 htextOutput ?
"<red><run sc_name info -odD {}; ::windows::stats::Refresh>" :
"",
6840 bothscore[STATS_OPP][RESULT_Draw],
6841 htextOutput ?
"</run></red>" :
"",
6842 htextOutput ?
"<red><run sc_name info -olL {}; ::windows::stats::Refresh>" :
"",
6843 bothscore[STATS_OPP][RESULT_Black],
6844 htextOutput ?
"</run></red>" :
"",
6845 score / 2, decimalPointChar, score % 2 ?
'5' :
'0',
6846 htextOutput ?
"<red><run sc_name info -oaA {}; ::windows::stats::Refresh>" :
"",
6847 totalcount[STATS_OPP],
6848 htextOutput ?
"</run></red></tt>" :
"");
6849 Tcl_AppendResult (ti, temp, newline, NULL);
6854 for (color =
WHITE; color <=
BLACK; color++) {
6855 for (
uint count = 0; count < 6; count++) {
6856 int mostPlayedIdx = -1;
6857 uint mostPlayed = 0;
6858 for (
uint i=0; i < 50; i++) {
6859 if (ecoCount[color][i] > mostPlayed) {
6861 mostPlayed = ecoCount[
color][i];
6864 if (mostPlayed > 0) {
6866 const char * s = (color ==
WHITE ?
"PInfoMostWhite" :
6868 Tcl_AppendResult (ti, newline, startHeading,
6870 endHeading, newline, NULL);
6871 }
else if (count == 3) {
6872 Tcl_AppendResult (ti, newline, NULL);
6874 Tcl_AppendResult (ti,
" ", NULL);
6876 temp[0] = mostPlayedIdx / 10 +
'A';
6877 temp[1] = mostPlayedIdx % 10 +
'0';
6880 Tcl_AppendResult (ti,
"<blue><run ::windows::eco::Refresh ",
6883 Tcl_AppendResult (ti, temp, NULL);
6885 Tcl_AppendResult (ti,
"</run></blue>", NULL);
6887 sprintf (temp,
":%3u (%u%%)", mostPlayed,
6888 ecoScore[color][mostPlayedIdx] * 50 / mostPlayed);
6889 Tcl_AppendResult (ti, temp, NULL);
6890 ecoCount[
color][mostPlayedIdx] = 0;
6912 const char * usage = \
6913 "Usage: sc_name match [-elo] <nameType> <prefix> <maxMatches>";
6916 int argsleft = argc - 2;
6917 bool eloMode =
false;
6918 if (argsleft < 3) {
return errorResult (ti, usage); }
6919 if (argv[arg][0] ==
'-' &&
strIsPrefix (argv[arg],
"-elo")) {
6924 if (argsleft != 3) {
6933 const char * prefix = argv[arg++];
6935 if (maxMatches == 0) {
return TCL_OK; }
6937 for (
auto nameID : matches) {
6941 Tcl_AppendElement (ti, str);
6958 if (firstDate ==
ZERO_DATE || date < firstDate) firstDate =
date;
6959 if (date > lastDate) lastDate =
date;
6966 const std::vector<PlayerActivity>& activity_;
6967 enum { SORT_ELO, SORT_GAMES, SORT_OLDEST, SORT_NEWEST, SORT_NAME };
6971 : dbase_(dbase), sort_(sortOrder), activity_(activity) {
7000 if (compare == 0) { compare =
strCompare (name1, name2); }
7009 const char * usage =
"Usage: sc_name plist [-<option> <value> ...]";
7012 const char * namePrefix =
"";
7019 static const char * options [] = {
7020 "-name",
"-minElo",
"-maxElo",
"-minGames",
"-maxGames",
7021 "-size",
"-sort", NULL
7024 OPT_NAME, OPT_MINELO, OPT_MAXELO, OPT_MINGAMES, OPT_MAXGAMES,
7029 static const char * sortModes [] = {
7030 "elo",
"games",
"oldest",
"newest",
"name", NULL
7033 SORT_ELO, SORT_GAMES, SORT_OLDEST, SORT_NEWEST, SORT_NAME
7036 int sortMode = SORT_NAME;
7040 while (arg+1 < argc) {
7041 const char * option = argv[arg];
7042 const char * value = argv[arg+1];
7046 case OPT_NAME: namePrefix = value;
break;
7060 if (arg != argc) {
return errorResult (ti, usage); }
7061 if (sortMode == -1)
return InvalidCommand (ti,
"sc_name plist -sort", sortModes);
7067 std::vector<idNumberT>
plist;
7068 for (
idNumberT id = 0;
id < nPlayers;
id++) {
7072 if (nGames < minGames || nGames > maxGames) {
continue; }
7073 if (elo < minElo || elo > maxElo) {
continue; }
7075 plist.push_back(
id);
7078 std::vector<PlayerActivity> activity(nPlayers);
7083 activity[ie->
GetWhite()].addDate(date);
7084 activity[ie->
GetBlack()].addDate(date);
7088 count = std::min(count, plist.size());
7089 std::partial_sort(plist.begin(), plist.begin() + count, plist.end(),
PListSort(dbase, activity, sortMode));
7093 for (
size_t i=0; i < count; i++) {
7101 res.push_back(info);
7130 const char * options[] = {
7131 "-update",
"-test",
"-change",
"-filter" };
7133 OPT_UPDATE, OPT_TEST, OPT_CHANGE, OPT_FILTER
7136 bool updateIndexFile =
true;
7137 bool testOnly =
false;
7138 bool overwrite =
false;
7139 bool filterOnly =
false;
7142 while (arg+1 < argc) {
7146 case OPT_UPDATE: updateIndexFile = value;
break;
7147 case OPT_TEST: testOnly = value;
break;
7148 case OPT_CHANGE: overwrite = value;
break;
7149 case OPT_FILTER: filterOnly = value;
break;
7156 return UI_Result(ti,
ERROR,
"The current spellcheck file does not have " 7157 "Elo rating information.\n\n" 7158 "To use this function, you should load " 7159 "\"ratings.ssp\" (available from the Scid website) " 7160 "as your spellcheck file first.");
7165 uint numChangedRatings = 0;
7166 uint numChangedGames = 0;
7176 return (vElo[
id]) ? vElo[id]->
getElo(
date) : 0;
7187 unsigned nChanges = (eloWhite != 0) ? 1 : 0;
7188 nChanges += (eloBlack != 0) ? 1 : 0;
7190 numChangedRatings += nChanges;
7192 if (updateIndexFile) {
7193 if (eloWhite != 0) {
7197 if (eloBlack != 0) {
7207 std::string filter = (filterOnly) ?
"dbfilter" : dbase.
newFilter();
7216 return UI_Result(ti, changes.first, res);
7234 const char * filename = argv[2];
7237 if (newSpell.first !=
OK) {
7238 return UI_Result(ti, newSpell.first,
"Error reading name spellcheck file.");
7240 if (spellChk != NULL) {
delete spellChk; }
7241 spellChk = newSpell.second;
7259 uint maxCorrections = 20000;
7260 bool doSurnames =
false;
7261 bool ambiguous =
true;
7262 const char * usage =
"Usage: sc_name spellcheck [-max <integer>] [-surnames <boolean>] [-ambiguous <boolean>] players|events|sites|rounds";
7264 const char * options[] = {
7265 "-max",
"-surnames",
"-ambiguous", NULL
7268 OPT_MAX, OPT_SURNAMES, OPT_AMBIGUOUS
7272 while (arg+1 < argc) {
7273 const char * option = argv[arg];
7274 const char * value = argv[arg+1];
7277 if (option[0] ==
'-') { index =
strUniqueMatch (option, options); }
7282 if ( maxCorrections == 0 ) {
7283 maxCorrections = (
uint)-1;
7296 if (arg+1 != argc) {
return errorResult (ti, usage); }
7304 std::vector<std::string> tmpRes;
7306 uint correctionCount = 0;
7311 if (correctionCount >= maxCorrections)
break;
7313 if ((
id % 1000) == 0) {
7314 if (!progress.
report(
id, n))
break;
7319 if (frequency == 0)
continue;
7321 const char* origName = nb->
GetName(nt,
id);
7326 std::string
name = origName;
7332 size_t country = name.rfind(
" (");
7333 if (country != std::string::npos && (country + 6) == name.length()) {
7334 if (*(name.rbegin()) ==
')') name.erase(country);
7338 std::vector<const char*> corrections = sp.
find(nt, name.c_str());
7340 if (!ambiguous && corrections.size() > 1)
continue;
7342 if (nGenCorrections != 0 && corrections.size() == 0) {
7343 corrections.push_back(name.c_str());
7346 std::string correctCmd;
7347 const char* strAmbiguous = corrections.size() > 1 ?
"Ambiguous: " :
"";
7348 for (
size_t i=0; i < corrections.size(); i++) {
7349 if (strcmp(origName, corrections[i]) == 0) {
7350 if (corrections.size() != 1) {
7351 correctCmd.append(
"ERROR: " + name);
7355 if (i==0) correctionCount++;
7357 sprintf (tempStr,
"%s\"%s\"\t>> \"%s\" (%u)",
7362 correctCmd += tempStr;
7372 correctCmd += tempStr;
7377 correctCmd += tempStr;
7384 if (!correctCmd.empty()) tmpRes.push_back(correctCmd);
7387 std::sort(tmpRes.begin(), tmpRes.end());
7392 static const char* NAME_TYPE_STRING[] = {
"player",
"event",
"site",
"round"};
7393 sprintf (tempStr,
"Scid found %u %s name correction%s.\n",
7394 correctionCount, NAME_TYPE_STRING[nt],
7396 std::string res = tempStr;
7398 "Edit the list to remove any corrections you do not want.\n" 7399 "Only lines of the form:\n" 7400 " \"Old Name\" >> \"New Name\"\n" 7401 "(with no spaces before the \"Old Name\") are processed.\n" 7402 "You can discard a correction you do not want by deleting\n" 7403 "its line, or simply by adding a space or any other character\n" 7404 "at the start of the line.\n";
7407 "Note: player names with a surname only, such as \"Kramnik\",\n" 7408 "have not been corrected, since such corrections are often\n" 7409 "wrong. You can choose to also show surname-only corrections\n" 7410 "using the button below.\n";
7413 std::vector<std::string>::const_iterator it = tmpRes.begin();
7414 std::vector<std::string>::const_iterator it_Ambiguous =
7415 std::lower_bound(tmpRes.begin(), tmpRes.end(),
"Ambig");
7416 for (;it != it_Ambiguous; it++) {
7419 for (;it != tmpRes.end(); it++) {
7427 static const char * options [] = {
7428 "correct",
"edit",
"info",
"match",
"plist",
7429 "ratings",
"read",
"spellcheck",
"retrievename",
"elo",
7433 OPT_CORRECT, OPT_EDIT, OPT_INFO, OPT_MATCH, OPT_PLIST,
7434 OPT_RATINGS, OPT_READ, OPT_SPELLCHECK, OPT_RETRIEVENAME, OPT_ELO
7458 if (db->
isReadOnly() && index != OPT_RETRIEVENAME) {
7470 if (spellChk == NULL) {
7472 "A spellcheck file has not been loaded.\n\n" 7473 "You can load one from the Options menu.");
7480 case OPT_RETRIEVENAME:
7483 case OPT_SPELLCHECK:
7487 return sc_name_elo (ti, *spellChk, argc, argv);
7500 avgGameLength (
resultT result)
7511 if (count == 0) {
return 0; }
7512 return (sum + (count/2)) / count;
7516 sc_report (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
7518 static const char * options [] = {
7519 "avgLength",
"best",
"counts",
"create",
"eco",
"elo",
7520 "endmaterial",
"format",
"frequency",
"line",
"max",
"moveOrders",
7521 "notes",
"players",
"print",
"score",
"select",
"themes", NULL
7524 OPT_AVGLENGTH, OPT_BEST, OPT_COUNTS, OPT_CREATE, OPT_ECO, OPT_ELO,
7525 OPT_ENDMAT, OPT_FORMAT, OPT_FREQ, OPT_LINE, OPT_MAX, OPT_MOVEORDERS,
7526 OPT_NOTES, OPT_PLAYERS, OPT_PRINT, OPT_SCORE, OPT_SELECT, OPT_THEMES
7529 static const char * usage =
7530 "Usage: sc_report opening|player <command> [<options...>]";
7535 switch (argv[1][0]) {
7536 case 'O':
case 'o': report = reports[REPORT_OPENING];
break;
7537 case 'P':
case 'p': report = reports[REPORT_PLAYER];
break;
7548 if (index >= 0 && index != OPT_CREATE && report == NULL) {
7549 return errorResult (ti,
"No report has been created yet.");
7556 return errorResult (ti,
"Usage: sc_report player|opening avgLength 1|=|0|*");
7566 return errorResult (ti,
"Usage: sc_report opening|player best w|b|a|o|n <count>");
7570 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7585 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7587 Tcl_AppendResult (ti, report->
GetEco(), NULL);
7593 return errorResult (ti,
"Usage: sc_report opening|player elo white|black");
7599 if (argv[3][0] ==
'B' || argv[3][0] ==
'b') { color =
BLACK; }
7600 uint avg = report->
AvgElo (color, &count, &pct, &perf);
7611 translate (ti,
"OprepReportGames",
"Report games"),
7612 translate (ti,
"OprepAllGames",
"All games"));
7613 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7618 return errorResult (ti,
"Usage: sc_report opening|player format latex|html|text|ctext");
7625 return errorResult (ti,
"Usage: sc_report opening|player frequency 1|=|0|*");
7638 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7642 if (argc == 4 && argv[3][0] ==
'g') {
7644 }
else if (argc == 4 && argv[3][0] ==
'r') {
7647 return errorResult (ti,
"Usage: sc_report opening|player max games|rows");
7649 case OPT_MOVEORDERS:
7651 return errorResult (ti,
"Usage: sc_report opening|player moveOrders <count>");
7655 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7659 if (argc < 4 || argc > 5) {
7660 return errorResult (ti,
"Usage: sc_report opening|player notes <0|1> [numrows]");
7667 if (nrows > 0) { report->
SetNumRows (nrows); }
7678 return errorResult (ti,
"Usage: sc_report opening|player players w|b <count>");
7681 if (argv[3][0] ==
'B' || argv[3][0] ==
'b') { color =
BLACK; }
7684 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7689 if (argc < 3 || argc > 6) {
7690 return errorResult (ti,
"Usage: sc_report opening|players print [numrows] [title] [comment]");
7695 if (nrows > 0) { report->
SetNumRows (nrows); }
7698 report->
PrintTable (dstr, argc > 4 ? argv[4] :
"",
7699 argc > 5 ? argv[5] :
"");
7700 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7708 percent = percent * 500;
7713 percent = percent / sum;
7725 report->
ThemeReport (dstr, argc - 3, (
const char **) argv + 3);
7726 Tcl_AppendResult (ti, dstr->
Data(), NULL);
7733 if (dstr != NULL) {
delete dstr; }
7747 uint maxThemeMoveNumber = 20;
7748 uint maxExtraMoves = 1;
7750 static const char * usage =
7751 "Usage: sc_report opening|player create [maxExtraMoves] [maxLines] [excludeMove]";
7753 uint reportType = 0;
7758 switch (argv[1][0]) {
7759 case 'O':
case 'o': reportType = REPORT_OPENING;
break;
7760 case 'P':
case 'p': reportType = REPORT_PLAYER;
break;
7773 if (maxLines == 0) { maxLines = 1; }
7775 const char * excludeMove =
"";
7776 if (argc > 5) { excludeMove = argv[5]; }
7777 if (excludeMove[0] ==
'-') { excludeMove =
""; }
7779 if (reports[reportType] != NULL) {
7780 delete reports[reportType];
7783 reports[reportType] =
report;
7791 for (
uint gnum=0, n = db->
numGames(); gnum < n; gnum++) {
7792 if ((gnum % 2000) == 0) {
7793 if (!progress.
report(gnum, n))
break;
7800 return errorResult (ti,
"Error reading game file.");
7807 if (scratchGame->
AtEnd()) ply = 0;
7811 maxExtraMoves, maxThemeMoveNumber);
7812 if (report->
Add (line)) {
7834 static const char * usage =
7835 "Usage: sc_report opening|player select <op|eg|note> <number>";
7840 switch (argv[1][0]) {
7841 case 'O':
case 'o': report = reports[REPORT_OPENING];
break;
7842 case 'P':
case 'p': report = reports[REPORT_PLAYER];
break;
7847 char type = tolower (argv[3][0]);
7851 uint * match = matches;
7853 while (*match != 0) {
7854 uint gnum = *match - 1;
7856 uint ply = *match + 1;
7870 sc_tree (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
7872 static const char * options [] = {
7873 "best",
"move",
"positions",
"search",
"size",
7874 "cachesize",
"cacheinfo", NULL
7877 TREE_BEST, TREE_MOVE, TREE_POSITIONS, TREE_SEARCH, TREE_SIZE,
7878 TREE_CACHESIZE, TREE_CACHEINFO
7888 case TREE_POSITIONS:
7898 case TREE_CACHESIZE:
7901 case TREE_CACHEINFO:
7922 return errorResult (ti,
"Usage: sc_tree move <baseNum> <lineNum>");
7929 if (argv[3][0] ==
'r' &&
strIsPrefix (argv[3],
"random")) {
7931 if (total == 0) {
return TCL_OK; }
7932 uint r = rand() % total;
7943 if (selection < 1 || selection > (
int)(base->
tree.
moveCount)) {
7953 if (! isalpha(node->
san[0])) {
7957 Tcl_AppendResult (ti, node->
san, NULL);
7976 for (
uint inner=outer+1; inner < tree->
moveCount; inner++) {
7979 switch (sortMethod) {
7995 if (toMove ==
BLACK) { result = -result; }
8005 tree->
node[outer] = tree->
node[inner];
8006 tree->
node[inner] = temp;
8019 static const char * usageStr =
8020 "Usage: sc_tree search [-hideMoves <0|1>] [-sort alpha|eco|frequency|score]";
8023 static const char * sortOptions[] = {
8024 "alpha",
"eco",
"frequency",
"score", NULL
8028 bool hideMoves =
false;
8029 const bool listMode =
false;
8030 bool inFilterOnly =
false;
8034 static std::set<scidBaseT**> search_pool;
8039 int argsLeft = (argc - arg);
8040 if (argsLeft % 2 != 0) {
return errorResult (ti, usageStr); }
8042 while (arg < argc) {
8045 }
else if (
strIsPrefix (argv[arg],
"-hideMoves")) {
8050 }
else if (
strIsPrefix (argv[arg],
"-filtered")) {
8053 search_pool.clear();
8061 if (sortMethod < 0) {
return errorResult (ti, usageStr); }
8064 search_pool.insert(&base);
8073 bool foundInCache =
false;
8075 if (! inFilterOnly) {
8082 foundInCache =
true;
8087 if (!foundInCache) {
8104 if ((i % 5000) == 0) {
8105 if (!progress.
report(i,n) || search_pool.count(&base) == 0) {
8110 if (inFilterOnly && filter.
get(i) == 0) {
continue; }
8113 if (ie->
GetLength() == 0) { skipcount++;
continue; }
8117 bool foundMatch =
false;
8121 if (ply < -1) { skipcount++;
continue; }
8166 search_pool.erase(&base);
8167 return errorResult (ti,
"Error reading game file.");
8169 Game *g = scratchGame;
8178 if (ply > 255) { ply = 255; }
8182 for (search = 0; search < tree->
moveCount; search++, node++) {
8193 search_pool.erase(&base);
8239 if (!foundInCache) {
8246 * 500 / node->
total;
8249 if (ecoBook != NULL) {
8254 ecoT eco = ecoBook->findECO(&tmpPos);
8264 if (!foundInCache && !inFilterOnly) {
8270 search_pool.erase(&base);
8275 const char * titleRow =
8276 " Move ECO Frequency Score AvElo Perf AvYear %Draws";
8277 titleRow =
translate (ti,
"TreeTitleRow", titleRow);
8278 output->
Append (titleRow);
8283 for (
uint count=0; count < tree->
moveCount; count++, node++) {
8303 strcpy(tempTrans, node->
san);
8307 if (ecoStr[0] == 0) {
strCopy (ecoStr,
"{}"); }
8308 sprintf (temp,
"%2u %-6s %-5s %7u %3d%c%1d %3d%c%1d",
8310 hideMoves ?
"---" : tempTrans,
8311 hideMoves ?
"{}" : ecoStr,
8321 sprintf (temp,
"\n%2u: %-6s %-5s %7u:%3d%c%1d%% %3d%c%1d%%",
8323 hideMoves ?
"---" : tempTrans,
8324 hideMoves ?
"" : ecoStr,
8336 strCopy (temp, listMode ?
" {}" :
" ");
8338 sprintf (temp,
" %4u", avgElo);
8342 strCopy (temp, listMode ?
" {}" :
" ");
8344 sprintf (temp,
" %4u", perf);
8348 strCopy (temp, listMode ?
" {}" :
" ");
8350 sprintf (temp,
" %4u", avgYear);
8354 sprintf (temp,
" %3d%%", (pctDraws + 5) / 10);
8358 Tcl_AppendElement (ti, (
char *) output->
Data());
8367 uint64_t eloSum = 0;
8368 uint64_t eloCount = 0;
8369 uint64_t perfSum = 0;
8370 uint64_t perfCount = 0;
8371 uint64_t yearCount = 0;
8372 uint64_t yearSum = 0;
8375 for (
uint count=0; count < tree->
moveCount; count++, node++) {
8386 totalScore = totalScore * 500 / tree->
totalCount;
8388 if (eloCount >= 10) {
8389 avgElo = eloSum / eloCount;
8392 if (perfCount >= 10) {
8393 perf = perfSum / perfCount;
8394 uint score = (totalScore + 5) / 10;
8400 sprintf (temp,
"%2u %-6s %-5s %7u %3d%c%1d %3d%c%1d",
8405 100, decimalPointChar, 0,
8406 totalScore / 10, decimalPointChar, totalScore % 10);
8409 const char * totalString =
translate (ti,
"TreeTotal:",
"TOTAL:");
8410 output->
Append (
"\n_______________________________________________________________\n");
8411 sprintf (temp,
"%-12s %7u:100%c0%% %3d%c%1d%%",
8412 totalString, tree->
totalCount, decimalPointChar,
8413 totalScore / 10, decimalPointChar, totalScore % 10);
8417 output->
Append (listMode ?
" {}" :
" ");
8419 sprintf (temp,
" %4u", avgElo);
8423 output->
Append (listMode ?
" {} " :
" ");
8425 sprintf (temp,
" %4u", perf);
8428 if (yearCount == 0) {
8429 output->
Append (listMode ?
" {}" :
" ");
8431 sprintf (temp,
" %4u", static_cast<uint>((yearSum + (yearCount/2)) / yearCount));
8435 sprintf (temp,
" %3d%%", (pctDraws + 5) / 10);
8438 Tcl_AppendElement (ti, (
char *) output->
Data());
8446 Tcl_AppendResult (ti, output->
Data(), NULL);
8459 return errorResult (ti,
"Usage: sc_tree cachesize <base> <size>");
8472 return errorResult (ti,
"Usage: sc_tree cacheinfo <base>");
8488 sc_search (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
8490 static const char * options [] = {
8491 "board",
"header",
"material", NULL
8493 enum { OPT_BOARD, OPT_HEADER, OPT_MATERIAL };
8532 int argc,
const char** argv) {
8533 ASSERT(dbase !=
nullptr && filter !=
nullptr);
8535 const char* usageStr =
8536 "Usage: sc_search board <filterOp> <searchType> <searchInVars> <flip>";
8543 bool useHpSigSpeedup =
false;
8546 switch (argv[3][0]) {
8549 useHpSigSpeedup =
true;
8553 useHpSigSpeedup =
true;
8595 size_t startFilterCount = filter->
size();
8602 if ((gameNum % 5000) == 0) {
8603 if (!progress.
report(gameNum, n))
break;
8607 if (filter.
get(gameNum) == 0) {
8612 if (filter.
get(gameNum) != 0) {
8618 filter.
set (gameNum, 1);
8625 filter.
set (gameNum, 0);
8634 bool possibleMatch =
true;
8635 bool possibleFlippedMatch =
flip;
8641 if (useHpSigSpeedup && hpSig != 0xFFFF) {
8644 possibleMatch =
false;
8646 if (possibleFlippedMatch) {
8648 possibleFlippedMatch =
false;
8656 if (possibleMatch) {
8660 possibleMatch =
false;
8663 if (possibleFlippedMatch) {
8667 possibleFlippedMatch =
false;
8672 if (!possibleMatch && !possibleFlippedMatch) {
8673 filter.
set (gameNum, 0);
8680 return errorResult (ti,
"Error reading game file.");
8686 if (ply == 0 && possibleMatch) {
8687 if (g->
ExactMatch (pos, NULL, NULL, searchType)) {
8691 if (ply == 0 && possibleFlippedMatch) {
8692 if (g->
ExactMatch (posFlip, NULL, NULL, searchType)) {
8696 if (ply == 0 && possibleMatch) {
8702 if (ply == 0 && possibleFlippedMatch) {
8710 if (possibleMatch) {
8716 if (ply == 0 && possibleFlippedMatch) {
8723 if (ply > 255) { ply = 255; }
8724 filter.
set (gameNum, ply);
8728 if (flip) {
delete posFlip; }
8733 if (gameNum != dbase->
numGames()) {
8736 sprintf (temp,
"%lu / %lu (%d%c%02d s)",
8737 static_cast<unsigned long>(filter->
size()),
8738 static_cast<unsigned long>(startFilterCount),
8739 centisecs / 100, decimalPointChar, centisecs % 100);
8740 Tcl_AppendResult (ti, temp, NULL);
8741 #ifdef SHOW_SKIPPED_STATS 8742 sprintf(temp,
" Skipped %u games.", skipcount);
8743 Tcl_AppendResult (ti, temp, NULL);
8771 newPatt->
next = pattHead;
8783 nextPatt = patt->
next;
8785 my_Tcl_Free((
char*)patt);
8810 ASSERT (str != NULL && patt != NULL);
8815 const char * flagStr = str;
8817 const char * colorPieceStr = str;
8819 const char * fyleStr = str;
8821 const char * rankStr = str;
8824 if (*colorPieceStr ==
'?') {
8831 switch (tolower(*colorPieceStr)) {
8832 case 'w': color =
WHITE;
break;
8833 case 'b': color =
BLACK;
break;
8834 default:
return ERROR;
8839 switch (tolower(colorPieceStr[1])) {
8840 case 'k': p =
KING;
break;
8841 case 'q': p =
QUEEN;
break;
8842 case 'r': p =
ROOK;
break;
8843 case 'b': p =
BISHOP;
break;
8844 case 'n': p =
KNIGHT;
break;
8845 case 'p': p =
PAWN;
break;
8846 default:
return ERROR;
8856 }
else if (ch >=
'a' && ch <=
'h') {
8866 }
else if (ch >=
'1' && ch <=
'8') {
8887 uint matchLength = 1;
8892 max[
WM] = max[
BM] = 9;
8898 bool oppBishops =
true;
8899 bool sameBishops =
true;
8906 const char * options[] = {
8907 "wq",
"bq",
"wr",
"br",
"wb",
"bb",
"wn",
"bn",
8908 "wp",
"bp",
"wm",
"bm",
"flip",
"filter",
"range",
8909 "length",
"bishops",
"diff",
"pattern", NULL
8912 OPT_WQ, OPT_BQ, OPT_WR, OPT_BR, OPT_WB, OPT_BB, OPT_WN, OPT_BN,
8913 OPT_WP, OPT_BP, OPT_WM, OPT_BM, OPT_FLIP, OPT_FILTER, OPT_RANGE,
8914 OPT_LENGTH, OPT_BISHOPS, OPT_DIFF, OPT_PATTERN
8918 while (arg+1 < argc) {
8919 const char * option = argv[arg];
8920 const char * value = argv[arg+1];
8923 if (option[0] ==
'-') {
8926 uint counts [2] = {0, 0};
8927 if (index >= OPT_WQ && index <= OPT_BM) {
8933 case OPT_WQ: min[
WQ] = counts[0]; max[
WQ] = counts[1];
break;
8934 case OPT_BQ: min[
BQ] = counts[0]; max[
BQ] = counts[1];
break;
8935 case OPT_WR: min[
WR] = counts[0]; max[
WR] = counts[1];
break;
8936 case OPT_BR: min[
BR] = counts[0]; max[
BR] = counts[1];
break;
8937 case OPT_WB: min[
WB] = counts[0]; max[
WB] = counts[1];
break;
8938 case OPT_BB: min[
BB] = counts[0]; max[
BB] = counts[1];
break;
8939 case OPT_WN: min[
WN] = counts[0]; max[
WN] = counts[1];
break;
8940 case OPT_BN: min[
BN] = counts[0]; max[
BN] = counts[1];
break;
8941 case OPT_WP: min[
WP] = counts[0]; max[
WP] = counts[1];
break;
8942 case OPT_BP: min[
BP] = counts[0]; max[
BP] = counts[1];
break;
8943 case OPT_WM: min[
WM] = counts[0]; max[
WM] = counts[1];
break;
8944 case OPT_BM: min[
BM] = counts[0]; max[
BM] = counts[1];
break;
8956 minPly = counts[0]; maxPly = counts[1];
8961 if (matchLength < 1) { matchLength = 1; }
8965 switch (toupper(value[0])) {
8966 case 'S': oppBishops =
false; sameBishops =
true;
break;
8967 case 'O': oppBishops =
true; sameBishops =
false;
break;
8968 default: oppBishops =
true; sameBishops =
true;
break;
8978 Tcl_AppendResult (ti,
"Invalid pattern: ", value, NULL);
8992 hpExMaskFlip =
hpSig_AddPawn (hpExMaskFlip, flipColor, fyle);
8997 flippedPatt =
addPattern (flippedPatt, &tempPatt);
9004 if (arg != argc) {
return errorResult (ti,
"Odd number of parameters."); }
9007 if (max[
WQ] < min[
WQ]) { max[
WQ] = min[
WQ]; }
9008 if (max[
BQ] < min[
BQ]) { max[
BQ] = min[
BQ]; }
9009 if (max[
WR] < min[
WR]) { max[
WR] = min[
WR]; }
9010 if (max[
BR] < min[
BR]) { max[
BR] = min[
BR]; }
9011 if (max[
WB] < min[
WB]) { max[
WB] = min[
WB]; }
9012 if (max[
BB] < min[
BB]) { max[
BB] = min[
BB]; }
9013 if (max[
WN] < min[
WN]) { max[
WN] = min[
WN]; }
9014 if (max[
BN] < min[
BN]) { max[
BN] = min[
BN]; }
9015 if (max[
WP] < min[
WP]) { max[
WP] = min[
WP]; }
9016 if (max[
BP] < min[
BP]) { max[
BP] = min[
BP]; }
9019 if (min[
WM] < min[WB]+min[WN]) { min[
WM] = min[
WB] + min[
WN]; }
9020 if (min[
BM] < max[BB]+min[BN]) { min[
BM] = min[
BB] + min[
BN]; }
9021 if (max[
WM] > max[WB]+max[WN]) { max[
WM] = max[
WB] + max[
WN]; }
9022 if (max[
BM] > max[BB]+max[BN]) { max[
BM] = max[
BB] + max[
BN]; }
9025 if (matDiff[0] > matDiff[1]) {
9026 int temp = matDiff[0]; matDiff[0] = matDiff[1]; matDiff[1] = temp;
9031 minFlipped[
WQ] = min[
BQ]; maxFlipped[
WQ] = max[
BQ];
9032 minFlipped[
WR] = min[
BR]; maxFlipped[
WR] = max[
BR];
9033 minFlipped[
WB] = min[
BB]; maxFlipped[
WB] = max[
BB];
9034 minFlipped[
WN] = min[
BN]; maxFlipped[
WN] = max[
BN];
9035 minFlipped[
WP] = min[
BP]; maxFlipped[
WP] = max[
BP];
9036 minFlipped[
WM] = min[
BM]; maxFlipped[
WM] = max[
BM];
9037 minFlipped[
BQ] = min[
WQ]; maxFlipped[
BQ] = max[
WQ];
9038 minFlipped[
BR] = min[
WR]; maxFlipped[
BR] = max[
WR];
9039 minFlipped[
BB] = min[
WB]; maxFlipped[
BB] = max[
WB];
9040 minFlipped[
BN] = min[
WN]; maxFlipped[
BN] = max[
WN];
9041 minFlipped[
BP] = min[
WP]; maxFlipped[
BP] = max[
WP];
9042 minFlipped[
BM] = min[
WM]; maxFlipped[
BM] = max[
WM];
9047 minPly = minPly * 2 - 1;
9048 maxPly = maxPly * 2;
9053 if (max[WQ] > 3 || max[BQ] > 3 || max[WR] > 3 || max[BR] > 3 ||
9054 max[WB] > 3 || max[BB] > 3 || max[WN] > 3 || max[BN] > 3) {
9066 Game * g = scratchGame;
9074 size_t startFilterCount = filter->
size();
9078 for (; gameNum < n; gameNum++) {
9079 if ((gameNum % 1000) == 0) {
9080 if (!progress.
report(gameNum, n))
break;
9084 if (filter.
get(gameNum) == 0) {
9089 if (filter.
get(gameNum) != 0) {
9095 filter.
set (gameNum, 1);
9100 filter.
set (gameNum, 0);
9108 filter.
set (gameNum, 0);
9113 bool possibleMatch =
true;
9114 bool possibleFlippedMatch =
flip;
9122 possibleMatch =
false;
9124 if (flip && checkMsig
9129 possibleFlippedMatch =
false;
9137 if (possibleMatch && hpExcludeMask !=
HPSIG_Empty) {
9140 if ((gameFinalHP & hpExcludeMask) != 0) {
9141 possibleMatch =
false;
9144 if (possibleFlippedMatch && hpExMaskFlip !=
HPSIG_Empty) {
9147 if ((gameFinalHP & hpExMaskFlip) != 0) {
9148 possibleFlippedMatch =
false;
9152 if (!possibleMatch && !possibleFlippedMatch) {
9153 filter.
set (gameNum, 0);
9164 bool result =
false;
9165 if (possibleMatch) {
9167 minPly, maxPly, matchLength,
9168 oppBishops, sameBishops,
9169 matDiff[0], matDiff[1]);
9171 if (result == 0 && possibleFlippedMatch) {
9174 flippedPatt, minPly, maxPly,
9175 matchLength, oppBishops, sameBishops,
9176 matDiff[0], matDiff[1]);
9183 if (b == 0) { b = 1; }
9184 filter.
set (gameNum, b);
9187 filter.
set (gameNum, 0);
9200 sprintf (temp,
"%lu / %lu (%d%c%02d s)",
9201 static_cast<unsigned long>(filter->
size()),
9202 static_cast<unsigned long>(startFilterCount),
9203 centisecs / 100, decimalPointChar, centisecs % 100);
9204 Tcl_AppendResult (ti, temp, NULL);
9205 #ifdef SHOW_SKIPPED_STATS 9206 sprintf(temp,
" Skipped %u games.", skipcount);
9207 Tcl_AppendResult (ti, temp, NULL);
9221 "gm",
"im",
"fm",
"wgm",
"wim",
"wfm",
"w",
"none" 9267 std::string sAnnotator;
9269 bool bAnnotated =
false;
9271 bool * wTitles = NULL;
9272 bool * bTitles = NULL;
9274 bool wToMove =
true;
9275 bool bToMove =
true;
9277 int pgnTextCount = 0;
9278 char ** sPgnText = NULL;
9280 const char * options[] = {
9281 "annotator",
"annotated",
9282 "wtitles",
"btitles",
"toMove",
9286 OPT_ANNOTATOR, OPT_ANNOTATED,
9287 OPT_WTITLES, OPT_BTITLES, OPT_TOMOVE,
9292 while (arg+1 < argc) {
9293 const char * option = argv[arg];
9294 const char * value = argv[arg+1];
9297 if (option[0] ==
'-') {
9332 if (Tcl_SplitList (ti, (
char *)value, &pgnTextCount,
9333 (CONST84
char ***) &sPgnText) != TCL_OK) {
9344 std::vector<bool> mWhite;
9345 if (wTitles != NULL && spellChk != NULL) {
9346 bool allTitlesOn =
true;
9348 if (! wTitles[t]) { allTitlesOn =
false;
break; }
9350 if (! allTitlesOn) {
9353 mWhite.resize(numNames,
true);
9354 for (i=0; i < numNames; i++) {
9357 const char * title = (pInfo) ? pInfo->
getTitle() :
"";
9376 std::vector<bool> mBlack;
9377 if (bTitles != NULL && spellChk != NULL) {
9378 bool allTitlesOn =
true;
9380 if (!bTitles[t]) { allTitlesOn =
false;
break; }
9382 if (! allTitlesOn) {
9385 mBlack.resize(numNames,
true);
9386 for (i=0; i < numNames; i++) {
9389 const char * title = (pInfo) ? pInfo->
getTitle() :
"";
9407 bool skipSearch =
false;
9408 if (sAnnotator.empty() && mWhite.empty() && mBlack.empty() &&
9409 bAnnotated ==
false && wToMove ==
true && bToMove ==
true &&
9410 pgnTextCount == 0) {
9418 if ((i % 5000) == 0) {
9419 if (!progress.
report(i,n)) {
9425 if (filter.
get(i) == 0)
continue;
9429 auto matchGameHeader = [&]() {
9432 if ((halfmoves % 2) == 0) {
9443 if (!mWhite.empty() && !mWhite[ie->
GetWhite()]) {
9446 if (!mBlack.empty() && !mBlack[ie->
GetBlack()]) {
9461 bool match = matchGameHeader();
9468 if (match && (pgnTextCount > 0 || !sAnnotator.empty())) {
9473 if (!sAnnotator.empty()) {
9475 scratchGame->
Clear();
9484 if(pgnTextCount > 0)
9486 scratchGame->
Clear();
9498 const char* buf = scratchGame->
WriteToPGN().first;
9499 for (
int m=0; m < pgnTextCount; m++) {
9500 if (match) { match =
strContains (buf, sPgnText[m]); }
9513 if (wTitles != NULL) {
delete[] wTitles; }
9514 if (bTitles != NULL) {
delete[] bTitles; }
9515 Tcl_Free ((
char *) sPgnText);
9527 sc_var (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
9529 static const char * options [] = {
9530 "count",
"number",
"create",
"delete",
"enter",
"exit",
"first",
9531 "level",
"list",
"moveInto",
"promote", NULL
9534 VAR_COUNT, VAR_NUMBER, VAR_CREATE, VAR_DELETE, VAR_ENTER, VAR_EXIT, VAR_FIRST,
9535 VAR_LEVEL, VAR_LIST, VAR_MOVEINTO, VAR_PROMOTE
9613 sc_var_list (ClientData, Tcl_Interp * ti,
int argc,
const char ** argv)
9618 for (
uint varNumber = 0; varNumber < varCount; varNumber++) {
9623 Tcl_AppendElement (ti, s);
9636 return errorResult (ti,
"Usage: sc_var enter <number>");
9658 sc_book (ClientData cd, Tcl_Interp * ti,
int argc,
const char ** argv)
9660 static const char * options [] = {
9661 "load",
"close",
"moves",
"positions",
"movesupdate",
"update", NULL
9664 BOOK_LOAD, BOOK_CLOSE, BOOK_MOVE, BOOK_POSITIONS, BOOK_MOVES_UPDATE, BOOK_UPDATE,
9680 case BOOK_POSITIONS:
9686 case BOOK_MOVES_UPDATE:
9703 return errorResult (ti,
"Usage: sc_book load bookfile slot");
9710 if (bookstate == -1 ) {
9713 if (bookstate > 0 ) {
9732 return errorResult (ti,
"Usage: sc_book close slot");
9746 char moves[200] =
"";
9749 return errorResult (ti,
"Usage: sc_book moves slot");
9754 Tcl_AppendResult (ti, moves, NULL);
9763 char moves[200] =
"";
9766 return errorResult (ti,
"Usage: sc_book positions slot");
9771 Tcl_AppendResult (ti, moves, NULL);
9781 return errorResult (ti,
"Usage: sc_book update <probs> slot");
9794 return errorResult (ti,
"Usage: sc_book movesupdate <moves> <probs> slot tempfile");
int polyglot_open(const char *BookFile, const int BookNumber)
int sc_name_correct(ClientData, Tcl_Interp *ti, int argc, const char **argv)
#define PGN_STYLE_COMMENTS
void DumpHtmlBoard(DString *dstr, uint style, const char *dir, bool flip)
errorT Random(const char *material)
const IndexEntry * getIndexEntry(gamenumT g) const
void PrintCompactStr(char *cboard)
uint date_GetYear(dateT date)
int setUintResult(Tcl_Interp *ti, uint i)
int sc_base_export(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const uint NUM_COLOR_TYPES
int sc_move_forward(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_book_positions(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void deleteFilter(const char *filterId)
int polyglot_positions(char *moves, const char *fen, const int BookNumber)
errorT MoveIntoVariation(uint varNumber)
errorT setExtraInfo(const char *tagname, const char *new_value)
Store an extra information about the database (type, description, etc..)
bool pgnParseGame(const char *input, size_t inputLen, Game &game, PgnParseLog &log)
Convert PGN text into a SCID's Game object.
crosstableModeT BestMode(void)
uint strLength(const char *str)
bool GetStartFlag() const
int sc_filter_first(ClientData, Tcl_Interp *ti, int, const char **)
void Fill(byte value)
Sets all values.
void SetEventStr(const char *str)
int sc_name_match(ClientData, Tcl_Interp *ti, int argc, const char **argv)
pieceT piece_Type(pieceT p)
int sc_game_import(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int strExactMatch(const char *keyStr, const char **strTable)
const char * strTrimLeft(const char *target, const char *trimChars)
void MakeSANString(simpleMoveT *sm, char *s, sanFlagT flag)
int sc_name_info(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int polyglot_close(const int BookNumber)
int sc_pos_addNag(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetMaxThemeMoveNumber(uint x)
int sc_eco_game(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const uint OPTABLE_MAX_ROWS
int sc_pos_isPromo(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_game_pgn(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint AvgElo(colorT color, uint *count, uint *oppScore, uint *oppPerf)
void GetPrevMoveUCI(char *str) const
#define PGN_STYLE_INDENT_COMMENTS
const char * titleStr[NUM_TITLES]
bool SetPgnFormatFromString(const char *str)
const char * getTitle() const
uint PercentFreq(resultT result)
uint scid_TB_Init(const char *)
void SetDecimalPointChar(char ch)
const char * GetBlackName(const NameBase *nb) const
int sc_search_board(Tcl_Interp *ti, const scidBaseT *dbase, HFilter filter, int argc, const char **argv)
int sc_book_load(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const byte * GetHomePawnData() const
#define PGN_STYLE_UNICODE
int sc_game_tags_share(ClientData, Tcl_Interp *ti, int argc, const char **argv)
bool strEqual(const char *str1, const char *str2)
errorT FindExactName(nameT nt, const char *str, idNumberT *idPtr) const
Finds an exact full, case-sensitive name.
uint freq[NUM_RESULT_TYPES]
void SetMoveComment(const char *comment)
int str_prefix_len(ClientData, Tcl_Interp *ti, int argc, const char **argv)
#define PGN_STYLE_NO_NULL_MOVES
FastGame getGame(const IndexEntry *ie) const
const uint NUM_RESULT_TYPES
patternT * addPattern(patternT *pattHead, patternT *addPatt)
bool strIsPrefix(const char *prefix, const char *longStr)
void SetSearchDepth(uint ply)
const char * strFirstChar(const char *target, char matchChar)
UndoRedo< Game, 100 > gameAlterations
bool MaterialMatch(ByteBuffer *buf, byte *min, byte *max, patternT *pattern, int minPly, int maxPly, int matchLength, bool oppBishops, bool sameBishops, int minDiff, int maxDiff)
int sc_search_material(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetTiebreaks(bool b)
void AddEndMaterial(matSigT ms, bool inFilter)
simpleMoveT * Get(size_t index)
void SetBlackRatingType(byte b)
void restoreLocation(const GameSavedPos &savedPos)
bool operator<(const gNumListT &a) const
void SetSeparateScoreGroups(bool b)
static std::pair< errorT, std::unique_ptr< PBook > > ReadEcoFile(const char *FileName)
Read a file with a list of ECO codes and creates a PBook object.
resultT GetResult() const
const squareT NULL_SQUARE
int sc_move_addUCI(ClientData, Tcl_Interp *ti, int argc, const char **argv)
char * strDuplicate(const char *original)
const char * errMsgNotOpen(Tcl_Interp *ti)
const char * FindExtraTag(const char *tag) const
const Stats & getStats() const
Statistics.
void SetSwissColors(bool b)
void SetDeleteFlag(bool b)
bool scid_TB_Available(matSigT)
size_t normalize(std::string *name) const
const cachedTreeT * Lookup(Position *pos)
idNumberT GetSite() const
const errorT ERROR_FileWrite
UI_res_t sc_info_priority(UI_extra_t, UI_handle_t ti, int argc, const char **argv)
void init()
init() - initialize the pool of databases.
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 char SCID_VERSION_STRING[]
void scid_book_update(char *probs, const int BookNumber)
const char * GetWhiteName(const NameBase *nb) const
const errorT ERROR_BadArg
const char * GetEco() const
void SetWhiteElo(eloT elo)
const char * ratingTypeNames[17]
void AddPgnTag(const char *tag, const char *value)
const char * GetMoveComment() const
int sc_filter_prev(ClientData, Tcl_Interp *ti, int, const char **)
const char * GetEventName(const NameBase *nb) const
int sc_game_info(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_pos_isAt(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint getNameFreq(nameT nt, idNumberT id)
void PrintCompactStrFlipped(char *cboard)
idNumberT GetEvent() const
const resultT RESULT_Black
void initTreeNode(treeNodeT *tnode)
int sc_report_create(ClientData, Tcl_Interp *ti, int argc, const char **argv)
errorT DecodeNextMove(ByteBuffer *buf, simpleMoveT *sm)
int scid_book_movesupdate(char *moves, char *probs, const int BookNumber, char *tempfile)
int sc_name_plist(ClientData, Tcl_Interp *ti, int argc, const char **argv)
squareT strGetSquare(const char *str)
void SetEventDate(dateT date)
int strUniqueMatch(const char *keyStr, const char **strTable)
byte get(gamenumT gnum) const
errorT ReadFromCompactStr(const byte *str)
int Think(MoveList *mlist)
errorT RelocatePiece(squareT fromSq, squareT toSq)
const resultT RESULT_OPPOSITE[4]
void DoSimpleMove(simpleMoveT *sm)
bool hpSig_PossibleMatch(uint hpSig, const byte *changeList)
errorT DecodeTags(ByteBuffer *buf, bool storeTags)
void store(TElem *current)
Stores a copy of an element into the undo queue.
int sc_pos_hash(ClientData, Tcl_Interp *ti, int argc, const char **argv)
matSigT matsig_setCount(matSigT m, pieceT p, uint count)
int sc_var(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
errorT saveGame(Game *game, gamenumT replacedGameId=INVALID_GAMEID)
Add or replace a game into the database.
void strTrimMarkCodes(char *str)
int appendUintResult(Tcl_Interp *ti, uint i)
uint strPrefix(const char *s1, const char *s2)
errorT endTransaction(gamenumT gameId=INVALID_GAMEID)
Update caches and flush the database's files.
class SpellChecker - name spelling
const uint MAX_LEGAL_MOVES
const gamenumT INVALID_GAMEID
void SetRound(idNumberT id)
void setDuplicates(uint *duplicates)
const errorT ERROR_NoVariation
std::vector< uint32_t > generateHashMap(nameT nt) const
For every name generates a 32bit hash with the first 4 chars.
scidBaseT * getBase(int baseHandle)
getBase() - get a database from the pool.
int sc_game_pop(ClientData, Tcl_Interp *, int, const char **)
bool * parseTitles(const char *str)
matSigT GetFinalMatSig() const
dateT GetEventDate() const
errorT MoveToLocationInPGN(unsigned stopLocation)
int sc_game_push(ClientData, Tcl_Interp *, int argc, const char **argv)
byte Get(gamenumT index) const
Gets the value at index.
void SetMaxTableLines(uint nlines)
uint16_t GetNumHalfMoves() const
const char * GetName(nameT nt, idNumberT id) const
Retrieve a name.
uint GetVarNumber() const
gamenumT Count() const
Return the number of nonzero values in filter.
void resize(size_t count)
int sc_eco_translate(ClientData, Tcl_Interp *ti, int argc, const char **argv)
#define PGN_STYLE_INDENT_VARS
void SetFormat(const char *str)
void SetResult(resultT res)
void date_DecodeToString(dateT date, char *str)
void scid_TB_SetCacheSize(uint)
colorT color_Flip(colorT c)
int sc_move_add(ClientData, Tcl_Interp *ti, int argc, const char **argv)
bool hpSig_Prefix(const byte *changeListA, const byte *changeListB)
int str_is_prefix(ClientData, Tcl_Interp *ti, int argc, const char **argv)
errorT search_index(const scidBaseT *base, HFilter &filter, int argc, const char **argv, const Progress &progress)
search_index() - search for games using game's IndexEntry info
int sc_tree(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
const resultT RESULT_Draw
const char * errMsgSearchInterrupted(Tcl_Interp *ti)
int sc_tree_cachesize(ClientData, Tcl_Interp *ti, int argc, const char **argv)
transmsg
TODO Put in the right letters for greek.
int sc_game_moves(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void GetNextMoveUCI(char *str)
byte GetWhiteRatingType() const
uint sc_base_duplicates(scidBaseT *dbase, UI_handle_t ti, int argc, const char **argv)
int sc_move_back(ClientData, Tcl_Interp *ti, int argc, const char **argv)
#define DATE_MAKE(y, m, d)
int sc_tree_cacheinfo(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetWhiteStr(const char *str)
const uint HPSIG_StdStart
const char * GetPreviousMoveComment() const
Return the comment on the move previously played by CurrentPos->ToMove If there are no previous moves...
void SetPosition(Position *pos)
void beginTransaction()
This function must be called before modifying the games of the database.
void TopPlayers(DString *dstr, colorT c, uint count)
#define PGN_STYLE_MOVENUM_SPACE
std::pair< errorT, size_t > transformIndex(HFilter hfilter, const Progress &progress, TOper entry_op)
Transform the IndexEntries of the games included in hfilter.
bool RemoveExtraTag(const char *tag)
byte game_parseNag(std::pair< const char *, const char *> strview)
int sc_base_piecetrack(ClientData, Tcl_Interp *ti, int argc, const char **argv)
UI_res_t sc_name_retrievename(UI_handle_t ti, const SpellChecker &sp, int argc, const char **argv)
int sc_pos_analyze(ClientData, Tcl_Interp *ti, int argc, const char **argv)
ushort GetCurrentPly() const
const char RESULT_STR[4][4]
int sc_game_startBoard(ClientData, Tcl_Interp *ti, int argc, const char **argv)
byte GetBlackRatingType() const
eloT getElo(dateT date) const
const treeT & getTree() const
int sc_game_firstMoves(ClientData, Tcl_Interp *ti, int argc, const char **argv)
std::string newFilter()
A Filter is a selection of games, usually obtained searching the database.
int sc_eco_read(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_pos_isLegal(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetNumberedColumns(bool b)
This class stores the database's names (players, events, sites and rounds).
int sc_tree_move(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int main(int argc, char *argv[])
Search for an exact position (same material in the same squares).
const pieceT PIECE_FLIP[MAX_PIECE_TYPES]
uint GetFlagStr(char *dest, const char *flags) const
errorT RemoveNag(bool isMoveNag)
const pieceT * GetBoard() const
filterOpT strGetFilterOp(const char *str)
UI_res_t sc_name_ratings(UI_handle_t ti, scidBaseT &dbase, const SpellChecker &sp, int argc, const char **argv)
void SetSiteStr(const char *str)
void EndMaterialReport(DString *dstr, const char *repGames, const char *allGames)
int sc_pos_html(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void PrintStemLine(DString *dstr, uint format, bool exclude)
errorT LoadStandardTags(const IndexEntry *ie, const NameBase *nb)
const errorT ERROR_UserCancel
void SetThreeWin(bool threewin)
const matSigT MATSIG_Empty
const byte NAG_DubiousMove
bool Add(Position *pos, treeT *tree, Filter *filter)
void UndoSimpleMove(simpleMoveT *sm)
int sc_var_enter(ClientData, Tcl_Interp *ti, int argc, const char **argv)
resultT GetResult() const
static bool IsValidNameType(nameT nt)
Validate a nameT type.
int sc_tree_search(ClientData, Tcl_Interp *ti, int argc, const char **argv)
ushort GetFullMoveCount() const
char transPiecesChar(char c)
bool strIsCasePrefix(const char *prefix, const char *longStr)
int sc_game_novelty(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const resultT RESULT_White
void CalcSANStrings(sanListT *sanList, sanFlagT flag)
const matSigT MATSIG_StdStart
void SetRoundStr(const char *str)
void TopEcoCodes(DString *dstr, uint count)
void PrintFEN(char *str, uint flags) const
std::pair< errorT, size_t > transformNames(nameT nt, HFilter hfilter, const Progress &progress, const std::vector< std::string > &newNames, TInitFunc fnInit, TMapFunc getID)
Transform the names of the games included in hfilter.
int errorResult(Tcl_Interp *ti, errorT err, const char *errorMsg=0)
errorT saveGameHelper(Game *game, gamenumT gameId)
const uint MAX_PIECE_TYPES
bool strIsSurnameOnly(const char *name)
uint matsig_getCount(matSigT m, pieceT p)
void SetBlackStr(const char *str)
int appendCharResult(Tcl_Interp *ti, char ch)
uint appendUintElement(Tcl_Interp *ti, uint i)
static uint Performance(uint oppAvg, uint percentage)
bool strIsUnknownName(const char *str)
idNumberT GetRound() const
idNumberT GetWhite() const
void strGetIntegers(const char *str, int *results, uint nResults)
const char * GetBlackStr() const
IndexEntry * FetchEntry(gamenumT g)
FetchEntry() - return a modifiable pointer to a game's IndexEntry.
bool GetDeleteFlag() const
long long CentiSecs() const
std::pair< const char *, unsigned > WriteToPGN(uint lineWidth=0, bool NewLineAtEnd=false, bool newLineToSpaces=true)
void SetExcludeMove(const char *s)
int sc_name_edit(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_game_save(ClientData, Tcl_Interp *ti, int argc, const char **argv)
TElem * redo(TElem *current)
Retrieve the last element from the redo queue.
int sc_filter_last(ClientData, Tcl_Interp *ti, int, const char **)
const char RESULT_CHAR[4]
void SetCountries(bool b)
byte GetStoredLineCode() const
std::string getMoveSAN(int ply_to_skip, int count)
size_t numCorrectNames(const nameT &nt) const
const errorT ERROR_InvalidMove
bool strAlphaContains(const char *longStr, const char *keyStr)
int sc_pos_probe(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
Implements a parser that converts PGN text into SCID's Game objects.
int sc_pos_getNags(ClientData, Tcl_Interp *ti, int, const char **)
int sc_info(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
uint MaterialValue(colorT c)
int strGetInteger(const char *str)
void closeAll()
closeAll() - close all the databases in the pool.
bool checkDuplicate(scidBaseT *base, const IndexEntry *ie1, const IndexEntry *ie2, dupCriteriaT *cr)
const NameNormalizer & getGeneralCorrections(const nameT &nt) const
uint GetNumVariations() const
errorT restoreFilter(Filter *filter) const
TElem * undo(TElem *current)
Retrieve the last element from the undo queue.
void DumpLatexBoard(DString *dstr, bool flip)
int InvalidCommand(Tcl_Interp *ti, const char *majorCmd, const char **minorCmds)
Position * GetCurrentPos()
simpleMoveT * GetCurrentMove()
const char * GetWhiteStr() const
byte GetWhiteRatingType() const
void SetEventDate(dateT edate)
void AddPgnStyle(uint mask)
errorT ReadCoordMove(simpleMoveT *m, const char *s, int slen, bool reverse)
bool IsPromoMove(squareT from, squareT to)
void SetPgnFormat(gameFormatT gf)
void sortTreeMoves(treeT *tree, int sortMethod, colorT toMove)
bool ExactMatch(Position *pos, ByteBuffer *buf, simpleMoveT *sm, gameExactMatchT searchType, bool *neverMatch)
int sc_book(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
BOOK functions.
int strCaseCompare(const char *str1, const char *str2)
decltype(extraTags_) const & GetExtraTags() const
uint getDuplicates(gamenumT gNum)
#define MATSIG_FlipColor(x)
int sc_info_limit(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetMoveOrderID(uint id)
void eco_ToExtendedString(ecoT ecoCode, char *ecoStr)
uint32_t strGetUnsigned(const char *str)
idNumberT GetBlack() const
void GenerateMoves(MoveList *mlist, pieceT mask, genMovesT genType, bool maybeInCheck)
std::vector< idNumberT > getFirstMatches(nameT nt, const char *str, size_t maxMatches) const
Get the first few matches of a name prefix.
int sc_info_tb(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetMinDepthCheckTime(uint depth)
const sanFlagT SAN_NO_CHECKTEST
void Set(gamenumT index, byte value)
Sets the value at index.
const sanFlagT SAN_CHECKTEST
int sc_eco_base(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint nResults[NUM_RESULT_TYPES]
const char * strNextWord(const char *str)
const PlayerElo * getPlayerElo(const char *name) const
pieceT piece_FromChar(int x)
char square_FyleChar(squareT sq)
std::vector< const char * > find(const nameT &nt, const char *name, uint nMaxRes=10) const
char * strAppend(char *target, const char *extra)
int setResult(Tcl_Interp *ti, const char *str)
int sc_var_first(ClientData, Tcl_Interp *ti, int, const char **)
int sc_pos_setComment(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint strGetRatingType(const char *name)
Defines the classes used to search for positions.
const errorT ERROR_FileReadOnly
const char INDEX_SUFFIX[]
static bool PgnFormatFromString(const char *str, gameFormatT *fmt)
UI_res_t UI_Result(UI_handle_t ti, errorT res)
UI_Result() - pass the result of an operation from c++ to UI.
void strTrimMarkup(char *str)
GameSavedPos currentLocation() const
int sc_report_select(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int getClipBase()
getClipBase() - return the handle of the clipbase
int sc_game_tags(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
int sc_pos_moves(ClientData, Tcl_Interp *ti, int argc, const char **)
eloT GetElo(idNumberT id) const
byte * GetNextNags() const
void SetDecimalChar(char c)
void push_back(Tcl_Obj *value)
int sc_pos_matchMoves(ClientData, Tcl_Interp *ti, int argc, const char **argv)
errorT MoveExitVariation()
void SetHtmlStyle(uint style)
bool report(size_t done, size_t total) const
int sc_move(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
bool scid_TB_compiled(void)
const uint RESULT_SCORE[4]
int setIntResult(Tcl_Interp *ti, int i)
colorT piece_Color(pieceT p)
errorT WriteEntry(const IndexEntry *ie, gamenumT idx)
WriteEntry() - modify a game in the Index.
void SetWhiteElo(eloT elo)
errorT DecodeStart(ByteBuffer *buf, bool decodeTags=false)
void strip(bool variations, bool comments, bool NAGs)
int polyglot_moves(char *moves, const char *fen, const int BookNumber)
void MoveToPly(int hmNumber)
int sc_var_list(ClientData, Tcl_Interp *ti, int argc, const char **argv)
ECO Classification functions.
dateT getBirthdate() const
void SetWhiteRatingType(byte b)
UI_res_t sc_name(UI_extra_t cd, UI_handle_t ti, int argc, const char **argv)
PListSort(scidBaseT *dbase, const std::vector< PlayerActivity > &activity, int sortOrder)
const char * strFirstWord(const char *str)
int sc_report(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
const char * translate(Tcl_Interp *ti, const char *name, const char *defaultText)
std::vector< scidBaseT::TreeStat > getTreeStat(const HFilter &filter)
const errorT ERROR_FileNotOpen
void ThemeReport(DString *dstr, uint argc, const char **argv)
const char RESULT_LONGSTR[4][8]
int sc_move_pgn(ClientData, Tcl_Interp *ti, int argc, const char **argv)
bool GetVariationsFlag() const
int sc_search_header(ClientData, Tcl_Interp *ti, scidBaseT *base, HFilter &filter, int argc, const char **argv)
UI_res_t sc_name_spellcheck(UI_handle_t ti, scidBaseT &dbase, const SpellChecker &sp, int argc, const char **argv)
const PlayerInfo * getPlayerInfo(const char *name, std::vector< const char *> *bio=0) const
const char * GetSiteStr() const
gamenumT numGames() const
void flipPattern(patternT *patt)
int sc_filter_stats(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void MakeLongStr(char *str)
const uint OPTABLE_MAX_TABLE_LINES
An heterogeneous container used to pass a list of values from c++ to UI.
bool VarExactMatch(Position *searchPos, gameExactMatchT searchType)
bool strContains(const char *longStr, const char *keyStr)
void strCopyExclude(char *target, const char *original, const char *excludeChars)
eloT GetBlackEstimateElo() const
int setUintWidthResult(Tcl_Interp *ti, uint i, uint width)
int sc_clipbase(ClientData, Tcl_Interp *ti, int argc, const char **argv)
CLIPBASE functions.
void SetNumRows(uint nrows)
const char * GetSiteName(const NameBase *nb) const
int sc_game_new(ClientData, Tcl_Interp *, int, const char **)
int sc_game_find(ClientData, Tcl_Interp *ti, int argc, const char **argv)
std::pair< Game *, bool > deprecated_push_pop
void strCopy(char *target, const char *original)
errorT scid_TB_Probe(Position *, int *)
int sc_filter_freq(scidBaseT *dbase, const HFilter &filter, Tcl_Interp *ti, int argc, const char **argv)
ecoT eco_FromString(const char *ecoStr)
bool GetCommentsFlag() const
unsigned GetPgnOffset() const
HFilter getFilter(const std::string &filterId) const
void PrintTable(DString *dstr, crosstableModeT mode, uint playerLimit, int currentGame)
int sc_eco_summary(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint AvgLength(resultT result)
void SetEvent(idNumberT id)
void BestGames(DString *dstr, uint count, const char *rtype)
int sc_name_read(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const byte * GetMaterial() const
int sc_pos_bestSquare(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void freePatternList(patternT *patt)
errorT AddPlayer(idNumberT id, const char *name, eloT elo, const SpellChecker *)
int sc_game_crosstable(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void SetSearchTime(uint ms)
idNumberT GetNumNames(nameT nt) const
uint hpSig_Final(const byte *changeList)
errorT parsePattern(const char *str, patternT *patt)
void exportGame(Game *g, FILE *exportFile, gameFormatT format, uint pgnStyle)
void RemovePgnStyle(uint mask)
void CacheResize(size_t max_size)
uint * SelectGames(char type, uint number)
bool probe_tablebase(Tcl_Interp *ti, int mode, DString *dstr)
uint32_t GetLength() const
int sc_search(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
const char * GetComment() const
void transPieces(char *s)
bool GetUnderPromoFlag() const
void SetBlackElo(eloT elo)
const char * strPlural(uint x)
Progress UI_CreateProgress(UI_handle_t ti)
UI_CreateProgress() - create a Progress object.
bool HasNonStandardStart(char *outFEN=nullptr) const
const IndexEntry * getIndexEntry_bounds(gamenumT g) const
int UI_Main(int argc, char *argv[], void(*exit)(void *))
UI_Main() - Init the UI.
resultT strGetResult(const char *str)
errorT Open(ICodecDatabase::Codec dbtype, fileModeT mode, const char *filename=0, const Progress &progress=Progress())
int sc_var_delete(ClientData, Tcl_Interp *ti, int, const char **)
int sc_game_tags_reload(ClientData, Tcl_Interp *, int, const char **)
eloT GetWhiteEstimateElo() const
int sc_move_addSan(ClientData, Tcl_Interp *ti, int argc, const char **argv)
ecoT eco_BasicCode(ecoT eco)
uint hpSig_AddPawn(uint hpSig, colorT color, fyleT fyle)
bool strGetBoolean(const char *str)
const char * GetEventStr() const
void strGetUnsigneds(const char *str, uint *results, uint nResults)
int sc_book_close(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void game_printNag(byte nag, char *str, bool asSymbol, gameFormatT format)
int sc_game_summary(ClientData, Tcl_Interp *ti, int argc, const char **argv)
int sc_filter_next(ClientData, Tcl_Interp *ti, int, const char **)
errorT AddMove(const simpleMoveT *sm)
bool matsig_isReachable(matSigT mStart, matSigT mTarget, bool promos, bool upromo)
int sc_book_update(ClientData, Tcl_Interp *ti, int argc, const char **argv)
dateT getDeathdate() const
byte GetBlackRatingType() const
const resultT RESULT_None
static uint FideCategory(eloT rating)
void SetBlackElo(eloT elo)
int sc_game_tags_get(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void GetPrevSAN(char *str)
const NameBase * getNameBase() const
void SetHashTableKilobytes(uint sizeKB)
void SetPawnTableKilobytes(uint sizeKB)
void PopularMoveOrders(DString *dstr, uint count)
int sc_base_tag(ClientData, Tcl_Interp *ti, int argc, const char **argv)
#define PGN_STYLE_SYMBOLS
#define PGN_STYLE_SHORT_HEADER
void eco_ToBasicString(ecoT ecoCode, char *ecoStr)
int sc_info_suffix(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const char * GetRoundStr() const
int sc_game_strip(ClientData, Tcl_Interp *ti, int argc, const char **argv)
const char * GetRoundName(const NameBase *nb) const
void SetWhiteRatingType(byte b)
int strCompare(const char *s1, const char *s2)
void PrintTable(DString *dstr, const char *title, const char *comment)
matSigT matsig_Make(const byte *materialCounts)
void translateECO(Tcl_Interp *ti, const char *strFrom, DString *dstrTo)
int sc_book_moves(ClientData, Tcl_Interp *ti, int argc, const char **argv)
uint date_GetMonth(dateT date)
void SetScidFlags(const char *s, size_t len)
int sc_base_inUse(ClientData, Tcl_Interp *ti, int argc, const char **argv)
errorT GetPartialMoveList(DString *str, uint plyCount)
static std::pair< errorT, SpellChecker * > Create(const char *filename, const Progress &progress)
Create() - Create a new SpellChecker object.
void set(gamenumT gnum, byte value)
pieceT piece_Make(colorT c, pieceT p)
char square_RankChar(squareT sq)
int sc_book_movesupdate(ClientData, Tcl_Interp *ti, int argc, const char **argv)
sanStringT list[MAX_LEGAL_MOVES]
class PlayerInfo - player informations
uint AddMoveOrder(Game *g)
static nameT NameTypeFromString(const char *str)
Match a string to a nameT.
const errorT ERROR_FileOpen
int sc_game_load(ClientData, Tcl_Interp *ti, int argc, const char **argv)
void strTrimDate(char *str)
char piece_Char(pieceT p)
bool GetPromotionsFlag() const
#define PGN_STYLE_STRIP_MARKS
void SetHypertextOutput()
int sc_eco(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
int sc_pos(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
int sc_game_tags_set(ClientData, Tcl_Interp *ti, int argc, const char **argv)
Progress UI_CreateProgressPosMask(UI_handle_t ti)
errorT Decode(ByteBuffer *buf, byte flags)
int sc_game(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
GAME functions.
dateT date_EncodeFromString(const char *str)
size_t listGames(const char *criteria, size_t start, size_t count, const HFilter &filter, gamenumT *destCont)
Retrieve a list of ordered game indexes sorted by criteria.
const sanFlagT SAN_MATETEST
int sc_pos_probe_board(ClientData, Tcl_Interp *ti, int argc, const char **argv)
treeNodeT node[MAX_TREE_NODES]
int sc_game_merge(ClientData, Tcl_Interp *ti, int argc, const char **argv)
dateT GetEventDate() const
errorT AddResult(uint gameNumber, idNumberT white, idNumberT black, resultT result, uint round, dateT date)
int sc_filter_old(ClientData cd, Tcl_Interp *ti, int argc, const char **argv)
FILTER functions.
const uint FEN_ALL_FIELDS
uint date_GetDay(dateT date)