{ "sSAN", ArgTrue, (void *) &appData.pvSAN[1], FALSE, FALSE },
{ "pairingEngine", ArgFilename, (void *) &appData.pairingEngine, TRUE, "" },
{ "defaultTourneyName", ArgFilename, (void *) &appData.defName, TRUE, "" },
+ { "eloThresholdAny", ArgInt, (void *) &appData.eloThreshold1, FALSE, (ArgIniType) 0 },
+ { "eloThresholdBoth", ArgInt, (void *) &appData.eloThreshold2, FALSE, (ArgIniType) 0 },
+ { "dateThreshold", ArgInt, (void *) &appData.dateThreshold, FALSE, (ArgIniType) 0 },
+ { "searchMode", ArgInt, (void *) &appData.searchMode, FALSE, (ArgIniType) 1 },
#if ZIPPY
{ "zippyTalk", ArgBoolean, (void *) &appData.zippyTalk, FALSE, (ArgIniType) ZIPPY_TALK },
}
int
+CompareWithRights(Board b1, Board b2)
+{
+ int rights = 0;
+ if(!CompareBoards(b1, b2)) return FALSE;
+ if(b1[EP_STATUS] != b2[EP_STATUS]) return FALSE;
+ /* compare castling rights */
+ if( b1[CASTLING][2] != b2[CASTLING][2] && (b2[CASTLING][0] != NoRights || b2[CASTLING][1] != NoRights) )
+ rights++; /* King lost rights, while rook still had them */
+ if( b1[CASTLING][2] != NoRights ) { /* king has rights */
+ if( b1[CASTLING][0] != b2[CASTLING][0] || b1[CASTLING][1] != b2[CASTLING][1] )
+ rights++; /* but at least one rook lost them */
+ }
+ if( b1[CASTLING][5] != b1[CASTLING][5] && (b2[CASTLING][3] != NoRights || b2[CASTLING][4] != NoRights) )
+ rights++;
+ if( b1[CASTLING][5] != NoRights ) {
+ if( b1[CASTLING][3] != b2[CASTLING][3] || b1[CASTLING][4] != b2[CASTLING][4] )
+ rights++;
+ }
+ return rights == 0;
+}
+
+int
Adjudicate(ChessProgramState *cps)
{ // [HGM] some adjudications useful with buggy engines
// [HGM] adjudicate: made into separate routine, which now can be called after every move
}
}
+int keys[EmptySquare+1];
+
+int
+PositionMatches(Board b1, Board b2)
+{
+ int r, f, sum=0;
+ switch(appData.searchMode) {
+ case 1: return CompareWithRights(b1, b2);
+ case 2:
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
+ if(b2[r][f] != EmptySquare && b1[r][f] != b2[r][f]) return FALSE;
+ }
+ return TRUE;
+ case 3:
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
+ if((b2[r][f] == WhitePawn || b2[r][f] == BlackPawn) && b1[r][f] != b2[r][f]) return FALSE;
+ sum += keys[b1[r][f]] - keys[b2[r][f]];
+ }
+ return sum==0;
+ case 4:
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
+ sum += keys[b1[r][f]] - keys[b2[r][f]];
+ }
+ return sum==0;
+ }
+ return TRUE;
+}
+
+GameInfo dummyInfo;
+
+int GameContainsPosition(FILE *f, ListGame *lg)
+{
+ int next, btm=0, plyNr=0, scratch=forwardMostMove+2&~1;
+ int fromX, fromY, toX, toY;
+ char promoChar;
+ static int initDone=FALSE;
+
+ if(!initDone) {
+ for(next = WhitePawn; next<EmptySquare; next++) keys[next] = rand()>>8 ^ rand()<<6 ^rand()<<20;
+ initDone = TRUE;
+ }
+ dummyInfo.variant = VariantNormal;
+ FREE(dummyInfo.fen); dummyInfo.fen = NULL;
+ dummyInfo.whiteRating = 0;
+ dummyInfo.blackRating = 0;
+ FREE(dummyInfo.date); dummyInfo.date = NULL;
+ fseek(f, lg->offset, 0);
+ yynewfile(f);
+ CopyBoard(boards[scratch], initialPosition); // default start position
+ while(1) {
+ yyboardindex = scratch + (plyNr&1);
+ quickFlag = 1;
+ next = Myylex();
+ quickFlag = 0;
+ switch(next) {
+ case PGNTag:
+ if(plyNr) return -1; // after we have seen moves, any tags will be start of next game
+ ParsePGNTag(yy_text, &dummyInfo);
+ if(dummyInfo.fen) ParseFEN(boards[scratch], &btm, dummyInfo.fen), free(dummyInfo.fen), dummyInfo.fen = NULL;
+ default:
+ continue;
+
+ case XBoardGame:
+ case GNUChessGame:
+ if(plyNr) return -1; // after we have seen moves, this is for new game
+ continue;
+ case AmbiguousMove: // we cannot reconstruct the game beyond these two
+ case ImpossibleMove:
+ case WhiteWins: // game ends here with these four
+ case BlackWins:
+ case GameIsDrawn:
+ case GameUnfinished:
+ return -1;
+
+ case IllegalMove:
+ if(appData.testLegality) return -1;
+ case WhiteCapturesEnPassant:
+ case BlackCapturesEnPassant:
+ case WhitePromotion:
+ case BlackPromotion:
+ case WhiteNonPromotion:
+ case BlackNonPromotion:
+ case NormalMove:
+ case WhiteKingSideCastle:
+ case WhiteQueenSideCastle:
+ case BlackKingSideCastle:
+ case BlackQueenSideCastle:
+ case WhiteKingSideCastleWild:
+ case WhiteQueenSideCastleWild:
+ case BlackKingSideCastleWild:
+ case BlackQueenSideCastleWild:
+ case WhiteHSideCastleFR:
+ case WhiteASideCastleFR:
+ case BlackHSideCastleFR:
+ case BlackASideCastleFR:
+ fromX = currentMoveString[0] - AAA;
+ fromY = currentMoveString[1] - ONE;
+ toX = currentMoveString[2] - AAA;
+ toY = currentMoveString[3] - ONE;
+ promoChar = currentMoveString[4];
+ break;
+ case WhiteDrop:
+ case BlackDrop:
+ fromX = next == WhiteDrop ?
+ (int) CharToPiece(ToUpper(currentMoveString[0])) :
+ (int) CharToPiece(ToLower(currentMoveString[0]));
+ fromY = DROP_RANK;
+ toX = currentMoveString[2] - AAA;
+ toY = currentMoveString[3] - ONE;
+ break;
+ }
+ // Move encountered; peform it. We need to shuttle between two boards, as even/odd index determines side to move
+ if(plyNr == 0) { // but first figure out variant and initial position
+ if(dummyInfo.variant != gameInfo.variant) return -1; // wrong variant
+ if(appData.eloThreshold1 && (dummyInfo.whiteRating < appData.eloThreshold1 && dummyInfo.blackRating < appData.eloThreshold1)) return -1;
+ if(appData.eloThreshold2 && (dummyInfo.whiteRating < appData.eloThreshold2 || dummyInfo.blackRating < appData.eloThreshold2)) return -1;
+ if(appData.dateThreshold && (!dummyInfo.date || atoi(dummyInfo.date) < appData.dateThreshold)) return -1;
+ if(btm) CopyBoard(boards[scratch+1], boards[scratch]), plyNr++;
+ if(PositionMatches(boards[scratch + plyNr], boards[currentMove])) return plyNr;
+ }
+ CopyBoard(boards[scratch + (plyNr+1&1)], boards[scratch + (plyNr&1)]);
+ plyNr++;
+ ApplyMove(fromX, fromY, toX, toY, promoChar, boards[scratch + (plyNr&1)]);
+ if(PositionMatches(boards[scratch + (plyNr&1)], boards[currentMove])) return plyNr;
+ }
+}
/* Load the nth game from open file f */
int
int gn = gameNumber;
ListGame *lg = NULL;
int numPGNTags = 0;
- int err;
+ int err, pos = -1;
GameMode oldGameMode;
VariantClass oldVariant = gameInfo.variant; /* [HGM] PGNvariant */
if (lg) {
fseek(f, lg->offset, 0);
GameListHighlight(gameNumber);
+ pos = lg->position;
gn = 1;
}
else {
AnalyzeFileEvent();
}
+ if (!matchMode && pos >= 0) {
+ ToNrEvent(pos); // [HGM] no autoplay if selected on position
+ } else
if (matchMode || appData.timeDelay == 0) {
ToEndEvent();
} else if (appData.timeDelay > 0) {
typedef struct _ListGame {
ListNode node;
int number;
+ int position;
unsigned long offset; /* Byte offset of game within file. */
GameInfo gameInfo; /* Note that some entries may be NULL. */
} ListGame;
int NPS[ENGINES];
Boolean autoKibitz;
int engineComments;
+ int eloThreshold1; /* [HGM] select */
+ int eloThreshold2;
+ int dateThreshold;
+ int searchMode;
char *userName;
int rewindIndex; /* [HGM] autoinc */
int sameColorGames; /* [HGM] alternate */
int PosFlags(int index);
extern signed char initialRights[BOARD_FILES]; /* [HGM] all rights enabled, set in InitPosition */
-
+int quickFlag;
int WhitePiece(piece)
ChessSquare piece;
}
rFilter = closure->rtIn; // [HGM] speed: only consider moves to given to-square
fFilter = closure->ftIn;
+ if(quickFlag) { // [HGM] speed: try without check test first, because if that is not ambiguous, we are happy
+ GenLegal(board, flags|F_IGNORE_CHECK, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn);
+ if(closure->count > 1) { // gamble did not pay off. retry with check test to resolve ambiguity
+ closure->count = closure->captures = 0;
+ closure->rf = closure->ff = closure->rt = closure->ft = 0;
+ closure->kind = ImpossibleMove;
+ GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn); // [HGM] speed: only pieces of requested type
+ }
+ } else
GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn); // [HGM] speed: only pieces of requested type
if (closure->count == 0) {
/* See if it's an illegal move due to check */
ChessMove CoordsToAlgebraic P((Board board, int flags,
int rf, int ff, int rt, int ft,
int promoChar, char out[MOVE_LEN]));
+
+extern int quickFlag;
#define OPT_MessageFont7 1955\r
#define OPT_SampleGameListFont 1956\r
#define OPT_ChooseGameListFont 1957\r
+#define OPT_elo1 1958\r
+#define OPT_elo2 1959\r
+#define OPT_date 1960\r
+#define OPT_elo1t 1961\r
+#define OPT_elo2t 1962\r
+#define OPT_datet 1963\r
+#define OPT_thresholds 1964\r
+#define OPT_Exact 1965\r
+#define OPT_Subset 1966\r
+#define OPT_Struct 1967\r
+#define OPT_Material 1968\r
\r
\r
// Next default values for new objects\r
};\r
\r
/* [AS] Setup the game list according to the specified filter */\r
-static int GameListToListBox( HWND hDlg, BOOL boReset, char * pszFilter, struct GameListStats * stats )\r
+static int GameListToListBox( HWND hDlg, BOOL boReset, char * pszFilter, struct GameListStats * stats, BOOL byPos )\r
{\r
ListGame * lg = (ListGame *) gameList.head;\r
int nItem;\r
+ char buf[MSG_SIZ];\r
BOOL hasFilter = FALSE;\r
int count = 0;\r
struct GameListStats dummy;\r
}\r
\r
for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){\r
- char * st = GameListLine(lg->number, &lg->gameInfo);\r
+ char * st = NULL;\r
BOOL skip = FALSE;\r
+ int pos = -1;\r
\r
if( hasFilter ) {\r
- if( ! SearchPattern( st, pszFilter ) ) {\r
- skip = TRUE;\r
- }\r
+ st = GameListLine(lg->number, &lg->gameInfo);\r
+ if( !SearchPattern( st, pszFilter) ) skip = TRUE;\r
+ }\r
+\r
+ if( !skip && byPos) {\r
+ if( (pos = GameContainsPosition(gameFile, lg)) < 0) skip = TRUE;\r
}\r
\r
+ lg->position = pos;\r
+\r
if( ! skip ) {\r
+ if(!st) st = GameListLine(lg->number, &lg->gameInfo);\r
SendDlgItemMessage(hDlg, OPT_GameListText, LB_ADDSTRING, 0, (LPARAM) st);\r
count++;\r
\r
stats->unfinished++;\r
}\r
\r
- free(st);\r
+ if(st) free(st);\r
lg = (ListGame *) lg->node.succ;\r
}\r
\r
/* Set font */\r
SendDlgItemMessage( hDlg, OPT_GameListText, WM_SETFONT, (WPARAM)font[boardSize][GAMELIST_FONT]->hf, MAKELPARAM(TRUE, 0 ));\r
\r
- count = GameListToListBox( hDlg, gameListDialog ? TRUE : FALSE, NULL, &stats );\r
+ count = GameListToListBox( hDlg, gameListDialog ? TRUE : FALSE, NULL, &stats, FALSE );\r
\r
SendDlgItemMessage( hDlg, IDC_GameListFilter, WM_SETTEXT, 0, (LPARAM) "" );\r
SendDlgItemMessage( hDlg, IDC_GameListFilter, EM_SETLIMITTEXT, MAX_FILTER_LENGTH, 0 );\r
/* [AS] End command replacement */\r
\r
switch (LOWORD(wParam)) {\r
- case IDOK:\r
case OPT_GameListLoad:\r
+ LoadOptionsPopup(hDlg);\r
+ return TRUE;\r
+ case IDOK:\r
nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);\r
if (nItem < 0) {\r
/* is this possible? */\r
SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, nItem, 0);\r
break; /* load the game*/\r
\r
- case OPT_GameListPrev:\r
+// case OPT_GameListPrev:\r
nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);\r
nItem--;\r
if (nItem < 0) {\r
break; /* load the game*/\r
\r
/* [AS] */\r
+ case OPT_GameListPrev:\r
case IDC_GameListDoFilter:\r
{\r
char filter[MAX_FILTER_LENGTH+1];\r
\r
if( GetDlgItemText( hDlg, IDC_GameListFilter, filter, sizeof(filter) ) >= 0 ) {\r
filter[ sizeof(filter)-1 ] = '\0';\r
- count = GameListToListBox( hDlg, TRUE, filter, &stats );\r
+ count = GameListToListBox( hDlg, TRUE, filter, &stats, LOWORD(wParam)!=IDC_GameListDoFilter );\r
GameListUpdateTitle( hDlg, _("Game List"), count, ((ListGame *) gameList.tailPred)->number, &stats );\r
}\r
}\r
PUSHBUTTON "Cancel",IDCANCEL,195,190,40,14\r
END\r
\r
-DLG_LoadOptions DIALOG DISCARDABLE 10, 18, 166, 55\r
+DLG_LoadOptions DIALOG DISCARDABLE 10, 18, 166, 184\r
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\r
CAPTION "Load Game Options"\r
FONT 8, "MS Sans Serif"\r
BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,4,160,10\r
EDITTEXT OPT_ASTimeDelay,16,16,28,14,ES_AUTOHSCROLL\r
LTEXT "seconds per move",OPT_AStext1,46,20,90,8,NOT WS_GROUP\r
- PUSHBUTTON "OK",IDOK,56,36,50,14,WS_GROUP\r
- PUSHBUTTON "Cancel",IDCANCEL,112,36,50,14\r
+ LTEXT "when filtering game list on position, use thresholds:",OPT_thresholds,4,36,160,8,NOT WS_GROUP\r
+ EDITTEXT OPT_elo1,16,50,28,14,ES_AUTOHSCROLL\r
+ LTEXT "Elo for at least one player",OPT_elo1t,46,54,90,8,NOT WS_GROUP\r
+ EDITTEXT OPT_elo2,16,70,28,14,ES_AUTOHSCROLL\r
+ LTEXT "Elo for both players",OPT_elo2t,46,74,90,8,NOT WS_GROUP\r
+ EDITTEXT OPT_date,16,90,28,14,ES_AUTOHSCROLL\r
+ LTEXT "or later year",OPT_datet,46,94,94,8,NOT WS_GROUP\r
+ CONTROL "Match exact position",OPT_Exact,"Button",\r
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,4,111,159,10\r
+ CONTROL "Match if position is subset",OPT_Subset,"Button",\r
+ BS_AUTORADIOBUTTON | WS_TABSTOP,4,124,159,10\r
+ CONTROL "Match material with exact pawn structure",OPT_Struct,"Button",\r
+ BS_AUTORADIOBUTTON | WS_TABSTOP,4,137,159,10\r
+ CONTROL "Match material",OPT_Material,"Button",\r
+ BS_AUTORADIOBUTTON | WS_TABSTOP,4,150,159,10\r
+ PUSHBUTTON "OK",IDOK,56,165,50,14,WS_GROUP\r
+ PUSHBUTTON "Cancel",IDCANCEL,112,165,50,14\r
END\r
\r
DLG_SaveOptions DIALOG DISCARDABLE 6, 17, 178, 119\r
BEGIN\r
LISTBOX OPT_GameListText,2,2,254,130,LBS_NOINTEGRALHEIGHT | \r
WS_VSCROLL | WS_HSCROLL | WS_TABSTOP\r
- PUSHBUTTON "&Load",OPT_GameListLoad,2,135,32,15\r
- PUSHBUTTON "&<",OPT_GameListPrev,38,135,22,15\r
- PUSHBUTTON "&>",OPT_GameListNext,64,135,24,15\r
- PUSHBUTTON "&Close",OPT_GameListClose,92,135,32,15\r
- PUSHBUTTON "Filter",IDC_GameListDoFilter,144,136,30,14\r
+ PUSHBUTTON "&Thresholds",OPT_GameListLoad,2,136,40,15\r
+ PUSHBUTTON "&Find Position",OPT_GameListPrev,45,136,48,15\r
+ PUSHBUTTON "&Close",OPT_GameListClose,96,136,30,15\r
+ PUSHBUTTON "&Filter",IDC_GameListDoFilter,149,136,25,14\r
EDITTEXT IDC_GameListFilter,178,136,78,14,ES_AUTOHSCROLL\r
END\r
\r
*\r
\*---------------------------------------------------------------------------*/\r
\r
+int\r
+LoadOptionsWhichRadio(HWND hDlg)\r
+{\r
+ return (IsDlgButtonChecked(hDlg, OPT_Exact) ? 1 :\r
+ (IsDlgButtonChecked(hDlg, OPT_Subset) ? 2 :\r
+ (IsDlgButtonChecked(hDlg, OPT_Struct) ? 3 :\r
+ (IsDlgButtonChecked(hDlg, OPT_Material) ? 4 : -1))));\r
+}\r
+\r
VOID\r
SetLoadOptionEnables(HWND hDlg)\r
{\r
{\r
char buf[MSG_SIZ];\r
float fnumber;\r
+ int ok;\r
\r
switch (message) {\r
case WM_INITDIALOG: /* message: initialize dialog box */\r
CheckDlgButton(hDlg, OPT_Autostep, FALSE);\r
}\r
SetLoadOptionEnables(hDlg);\r
+ SetDlgItemInt(hDlg, OPT_elo1, appData.eloThreshold1, FALSE);\r
+ SetDlgItemInt(hDlg, OPT_elo2, appData.eloThreshold2, FALSE);\r
+ SetDlgItemInt(hDlg, OPT_date, appData.dateThreshold, FALSE);\r
+ switch (appData.searchMode) {\r
+ case 1:\r
+ CheckDlgButton(hDlg, OPT_Exact, TRUE);\r
+ break;\r
+ case 2:\r
+ CheckDlgButton(hDlg, OPT_Subset, TRUE);\r
+ break;\r
+ case 3:\r
+ CheckDlgButton(hDlg, OPT_Struct, TRUE);\r
+ break;\r
+ case 4:\r
+ CheckDlgButton(hDlg, OPT_Material, TRUE);\r
+ break;\r
+ }\r
return TRUE;\r
\r
case WM_COMMAND: /* message: received a command */\r
} else {\r
appData.timeDelay = (float) -1.0;\r
}\r
+ appData.eloThreshold1 = GetDlgItemInt(hDlg, OPT_elo1, &ok, FALSE);\r
+ appData.eloThreshold2 = GetDlgItemInt(hDlg, OPT_elo2, &ok, FALSE);\r
+ appData.dateThreshold = GetDlgItemInt(hDlg, OPT_date, &ok, FALSE);\r
+ appData.searchMode = LoadOptionsWhichRadio(hDlg);\r
EndDialog(hDlg, TRUE);\r
return TRUE;\r
\r
XtSetArg(args[j], XtNleft, XtChainLeft); j++;
XtSetArg(args[j], XtNright, XtChainLeft); j++;
b_load =
- XtCreateManagedWidget(_("load"), commandWidgetClass, form, args, j);
+ XtCreateManagedWidget(_("thresholds"), commandWidgetClass, form, args, j);
XtAddCallback(b_load, XtNcallback, callback, client_data);
j = 0;
XtSetArg(args[j], XtNleft, XtChainLeft); j++;
XtSetArg(args[j], XtNright, XtChainLeft); j++;
b_loadprev =
- XtCreateManagedWidget(_("prev"), commandWidgetClass, form, args, j);
+ XtCreateManagedWidget(_("find position"), commandWidgetClass, form, args, j);
XtAddCallback(b_loadprev, XtNcallback, callback, client_data);
-
+#if 1
j = 0;
XtSetArg(args[j], XtNfromVert, viewport); j++;
XtSetArg(args[j], XtNfromHoriz, b_loadprev); j++;
b_loadnext =
XtCreateManagedWidget(_("next"), commandWidgetClass, form, args, j);
XtAddCallback(b_loadnext, XtNcallback, callback, client_data);
-
+#else
+ b_loadnext = b_loadprev;
+#endif
j = 0;
XtSetArg(args[j], XtNfromVert, viewport); j++;
XtSetArg(args[j], XtNfromHoriz, b_loadnext); j++;
XtSetArg(args[j], XtNbottom, XtChainBottom); j++;
XtSetArg(args[j], XtNleft, XtChainLeft); j++;
XtSetArg(args[j], XtNright, XtChainRight); j++;
- XtSetArg(args[j], XtNwidth, fw_width - 225 - squareSize); j++;
+ XtSetArg(args[j], XtNwidth, fw_width - 275 - squareSize); j++;
XtSetArg(args[j], XtNstring, filterString); j++;
XtSetArg(args[j], XtNdisplayCaret, False); j++;
XtSetArg(args[j], XtNresizable, True); j++;
}
static int
-GameListPrepare()
+GameListPrepare(int byPos)
{ // [HGM] filter: put in separate routine, to make callable from call-back
int nstrings;
ListGame *lg;
lg = (ListGame *) gameList.head;
listLength = 0;
while (nstrings--) {
+ int pos = -1;
line = GameListLine(lg->number, &lg->gameInfo);
- if(filterString[0] == NULLCHAR || SearchPattern( line, filterString ) ) {
+ if((filterString[0] == NULLCHAR || SearchPattern( line, filterString )) && (!byPos || (pos=GameContainsPosition(glc->fp, lg)) >= 0) ) {
*st++ = line; // [HGM] filter: make adding line conditional
listLength++;
}
+ lg->position = pos;
lg = (ListGame *) lg->node.succ;
}
*st = NULL;
GameListPopDown();
return;
}
+ if (strcmp(name, _("thresholds")) == 0) {
+ LoadOptionsProc();
+ return;
+ }
+ if (strcmp(name, _("find position")) == 0) {
+ if(GameListPrepare(True)) GameListReplace(); // crashes on empty list...
+ return;
+ }
listwidg = XtNameToWidget(glc->shell, "*form.viewport.list");
rs = XawListShowCurrent(listwidg);
if (strcmp(name, _("load")) == 0) {
XtGetValues(filterText, args, j);
safeStrCpy(filterString, name, sizeof(filterString)/sizeof(filterString[0]));
XawListHighlight(listwidg, 0);
- if(GameListPrepare()) GameListReplace(); // crashes on empty list...
+ if(GameListPrepare(False)) GameListReplace(); // crashes on empty list...
return;
}
-#if 0
+#if 1
index = atoi(glc->strings[index])-1; // [HGM] filter: read true index from sequence nr of line
if (cmailMsgLoaded) {
CmailLoadGame(glc->fp, index + 1, glc->filename, True);
free(glc->strings);
}
- GameListPrepare(); // [HGM] filter: code put in separate routine
+ GameListPrepare(False); // [HGM] filter: code put in separate routine
glc->fp = fp;
XtSetArg(args[j], XtNstring, &name); j++;
XtGetValues(filterText, args, j);
safeStrCpy(filterString, name, sizeof(filterString)/sizeof(filterString[0]));
- if(GameListPrepare()) GameListReplace(); // crashes on empty list...
+ if(GameListPrepare(False)) GameListReplace(); // crashes on empty list...
list = XtNameToWidget(glc->shell, "*form.viewport.list");
XawListHighlight(list, 0);
j = 0;
return glc && glc->up;
}
-int SaveGameListAsText(FILE *f)\r
-{\r
- ListGame * lg = (ListGame *) gameList.head;\r
- int nItem;\r
-\r
- if( !glc || ((ListGame *) gameList.tailPred)->number <= 0 ) {\r
- DisplayError("Game list not loaded or empty", 0);\r
- return False;\r
- }\r
-\r
- /* Copy the list into the global memory block */\r
- if( f != NULL ) {\r
+int SaveGameListAsText(FILE *f)
+{
+ ListGame * lg = (ListGame *) gameList.head;
+ int nItem;
+
+ if( !glc || ((ListGame *) gameList.tailPred)->number <= 0 ) {
+ DisplayError("Game list not loaded or empty", 0);
+ return False;
+ }
+
+ /* Copy the list into the global memory block */
+ if( f != NULL ) {
- lg = (ListGame *) gameList.head;\r
-\r
- for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){\r
- char * st = GameListLineFull(lg->number, &lg->gameInfo);\r
+ lg = (ListGame *) gameList.head;
+
+ for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){
+ char * st = GameListLineFull(lg->number, &lg->gameInfo);
char *line = GameListLine(lg->number, &lg->gameInfo);
if(filterString[0] == NULLCHAR || SearchPattern( line, filterString ) )
fprintf( f, "%s\n", st );
- free(st); free(line);\r
- lg = (ListGame *) lg->node.succ;\r
- }\r
-\r
+ free(st); free(line);
+ lg = (ListGame *) lg->node.succ;
+ }
+
fclose(f);
- return True;\r
+ return True;
}
- return False;\r
-}\r
+ return False;
+}
//--------------------------------- Game-List options dialog ------------------------------------------
Widget gameListOptShell, listwidg;
{ 0, 0, 0, NULL, (void*) &IcsOptionsOK, "", NULL, EndMark , "" }
};
+char *modeNames[] = { N_("Exact match"), N_("Shown position is subset"), N_("Same material and Pawn chain"), N_("Same material"), NULL };
+char *modeValues[] = { "1", "2", "3", "4" };
+char *searchMode;
+
+int LoadOptionsOK()
+{
+ appData.searchMode = atoi(searchMode);
+ return 1;
+}
+
Option loadOptions[] = {
{ 0, 0, 0, NULL, (void*) &appData.autoDisplayTags, "", NULL, CheckBox, N_("Auto-Display Tags") },
{ 0, 0, 0, NULL, (void*) &appData.autoDisplayComment, "", NULL, CheckBox, N_("Auto-Display Comment") },
{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("Auto-Play speed of loaded games\n(0 = instant, -1 = off):") },
{ 0, -1, 10000000, NULL, (void*) &appData.timeDelay, "", NULL, Fractional, N_("Seconds per Move:") },
-{ 0, 0, 0, NULL, NULL, "", NULL, EndMark , "" }
+{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("\nThresholds for position filtering in game list:") },
+{ 0, 0, 5000, NULL, (void*) &appData.eloThreshold1, "", NULL, Spin, N_("Elo of strongest player at least:") },
+{ 0, 0, 5000, NULL, (void*) &appData.eloThreshold2, "", NULL, Spin, N_("Elo of weakest player at least:") },
+{ 0, 0, 5000, NULL, (void*) &appData.dateThreshold, "", NULL, Spin, N_("No games before year:") },
+{ 1, 0, 180, NULL, (void*) &searchMode, (char*) modeNames, modeValues, ComboBox, N_("Seach mode:") },
+{ 0, 0, 0, NULL, (void*) &LoadOptionsOK, "", NULL, EndMark , "" }
};
Option saveOptions[] = {
String *prms;
Cardinal *nprms;
{
+ ASSIGN(searchMode, modeValues[appData.searchMode-1]);
GenericPopUp(loadOptions, _("Load Game Options"), 0);
}