void ics_update_width P((int new_width));
extern char installDir[MSG_SIZ];
VariantClass startVariant; /* [HGM] nicks: initial variant */
+Boolean abortMatch;
extern int tinyLayout, smallLayout;
ChessProgramStats programStats;
void PushTail P((int firstMove, int lastMove));
Boolean PopTail P((Boolean annotate));
+void PushInner P((int firstMove, int lastMove));
+void PopInner P((Boolean annotate));
void CleanupTail P((void));
ChessSquare FIDEArray[2][BOARD_FILES] = {
LoadEngine();
}
-extern char *engineName, *engineDir, *engineChoice, *engineLine, *nickName;
+extern char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;
extern Boolean isUCI, hasBook, storeVariant, v1, addToList;
-void Load(ChessProgramState *cps, int i)
+void
+Load(ChessProgramState *cps, int i)
{
- char *p, *q, buf[MSG_SIZ];
+ char *p, *q, buf[MSG_SIZ], command[MSG_SIZ];
if(engineLine[0]) { // an engine was selected from the combo box
snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
}
p = engineName;
while(q = strchr(p, SLASH)) p = q+1;
- if(*p== NULLCHAR) return;
- appData.chessProgram[i] = strdup(p);
+ if(*p== NULLCHAR) { DisplayError(_("You did not specify the engine executable"), 0); return; }
if(engineDir[0] != NULLCHAR)
appData.directory[i] = engineDir;
else if(p != engineName) { // derive directory from engine path, when not given
p[-1] = 0;
appData.directory[i] = strdup(engineName);
- p[-1] = '/';
+ p[-1] = SLASH;
} else appData.directory[i] = ".";
+ if(params[0]) {
+ snprintf(command, MSG_SIZ, "%s %s", p, params);
+ p = command;
+ }
+ appData.chessProgram[i] = strdup(p);
appData.isUCI[i] = isUCI;
appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
appData.hasOwnBookUCI[i] = hasBook;
isUCI ? " -fUCI" : "",
storeVariant ? " -variant " : "",
storeVariant ? VariantName(gameInfo.variant) : "");
-fprintf(debugFP, "new line: %s", buf);
firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1);
snprintf(firstChessProgramNames, len, "%s%s", q, buf);
if(q) free(q);
MatchEvent(int mode)
{ // [HGM] moved out of InitBackend3, to make it callable when match starts through menu
int dummy;
+ if(matchMode) { // already in match mode: switch it off
+ abortMatch = TRUE;
+ appData.matchGames = appData.tourneyFile[0] ? nextGame: matchGame; // kludge to let match terminate after next game.
+ ModeHighlight(); // kludgey way to remove checkmark...
+ return;
+ }
+// if(gameMode != BeginningOfGame) {
+// DisplayError(_("You can only start a match from the initial position."), 0);
+// return;
+// }
+ abortMatch = FALSE;
+ appData.matchGames = appData.defaultMatchGames;
/* Set up machine vs. machine match */
nextGame = 0;
NextTourneyGame(0, &dummy); // sets appData.matchGames if this is tourney, to make sure ReserveGame knows it
}
}
+Boolean pushed = FALSE;
void
ParsePV(char *pv, Boolean storeComments)
Boolean valid;
int nr = 0;
+ if (gameMode == AnalyzeMode && currentMove < forwardMostMove) {
+ PushInner(currentMove, forwardMostMove); // [HGM] engine might not be thinking on forwardMost position!
+ pushed = TRUE;
+ }
endPV = forwardMostMove;
do {
while(*pv == ' ' || *pv == '\n' || *pv == '\t') pv++; // must still read away whitespace
if(endPV < 0) return;
endPV = -1;
currentMove = forwardMostMove;
+ if(pushed) { PopInner(0); pushed = FALSE; } // restore shelved game contnuation
ClearPremoveHighlights();
DrawPosition(TRUE, boards[currentMove]);
}
case '-': bScore = 2; break;
case '=': wScore = bScore = 1; break;
case ' ':
- case '*': return NULL; // tourney not finished
+ case '*': return strdup("busy"); // tourney not finished
}
score[w] += wScore;
score[b] += bScore;
}
if(waitingForGame) resChar = ' '; // quit while waiting for round sync: unreserve already reserved game
- if(appData.tourneyFile[0]){ // [HGM] we are in a tourney; update tourney file with game result
+ if(appData.tourneyFile[0] && !abortMatch){ // [HGM] we are in a tourney; update tourney file with game result
ReserveGame(nextGame, resChar); // sets nextGame
if(nextGame > appData.matchGames) appData.tourneyFile[0] = 0, ranking = TourneyStandings(3); // tourney is done
} else roundNr = nextGame = matchGame + 1; // normal match, just increment; round equals matchGame
- if (nextGame <= appData.matchGames) {
+ if (nextGame <= appData.matchGames && !abortMatch) {
gameMode = nextGameMode;
matchGame = nextGame; // this will be overruled in tourney mode!
GetTimeMark(&pauseStart); // [HGM] matchpause: stipulate a pause
ModeHighlight();
endingGame = 0; /* [HGM] crash */
if(popupRequested) { // [HGM] crash: this calls GameEnds recursively through ExitEvent! Make it a harmless tail recursion.
- if(matchMode == TRUE) DisplayFatalError(ranking ? ranking : buf, 0, 0); else {
- matchMode = FALSE; appData.matchGames = matchGame = roundNr = 0;
- DisplayNote(ranking ? ranking : buf);
+ if(matchMode == TRUE) { // match through command line: exit with or without popup
+ if(ranking) {
+ if(strcmp(ranking, "busy")) DisplayFatalError(ranking, 0, 0);
+ else ExitEvent(0);
+ } else DisplayFatalError(buf, 0, 0);
+ } else { // match through menu; just stop, with or without popup
+ matchMode = FALSE; appData.matchGames = matchGame = roundNr = 0;
+ if(ranking){
+ if(strcmp(ranking, "busy")) DisplayNote(ranking);
+ } else DisplayNote(buf);
}
if(ranking) free(ranking);
}
// [HGM] vari: routines for shelving variations
void
-PushTail(int firstMove, int lastMove)
+PushInner(int firstMove, int lastMove)
{
int i, j, nrMoves = lastMove - firstMove;
- if(appData.icsActive) { // only in local mode
- forwardMostMove = currentMove; // mimic old ICS behavior
- return;
- }
- if(storedGames >= MAX_VARIATIONS-1) return;
-
// push current tail of game on stack
savedResult[storedGames] = gameInfo.result;
savedDetails[storedGames] = gameInfo.resultDetails;
storedGames++;
forwardMostMove = firstMove; // truncate game so we can start variation
+}
+
+void
+PushTail(int firstMove, int lastMove)
+{
+ if(appData.icsActive) { // only in local mode
+ forwardMostMove = currentMove; // mimic old ICS behavior
+ return;
+ }
+ if(storedGames >= MAX_VARIATIONS-2) return; // leave one for PV-walk
+
+ PushInner(firstMove, lastMove);
if(storedGames == 1) GreyRevert(FALSE);
}
-Boolean
-PopTail(Boolean annotate)
+void
+PopInner(Boolean annotate)
{
int i, j, nrMoves;
char buf[8000], moveBuf[20];
- if(appData.icsActive) return FALSE; // only in local mode
- if(!storedGames) return FALSE; // sanity
- CommentPopDown(); // make sure no stale variation comments to the destroyed line can remain open
-
storedGames--;
ToNrEvent(savedFirst[storedGames]); // sets currentMove
nrMoves = savedLast[storedGames] - currentMove;
}
gameInfo.resultDetails = savedDetails[storedGames];
forwardMostMove = currentMove + nrMoves;
+}
+
+Boolean
+PopTail(Boolean annotate)
+{
+ if(appData.icsActive) return FALSE; // only in local mode
+ if(!storedGames) return FALSE; // sanity
+ CommentPopDown(); // make sure no stale variation comments to the destroyed line can remain open
+
+ PopInner(annotate);
+
if(storedGames == 0) GreyRevert(TRUE);
return TRUE;
}