* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
void DisplayTwoMachinesTitle P(());
static void ExcludeClick P((int index));
void ToggleSecond P((void));
+void PauseEngine P((ChessProgramState *cps));
#ifdef WIN32
extern void ConsoleCreate();
extern char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;
extern Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick;
-static char resetOptions[] =
+static char resetOptions[] =
"-reuse -firstIsUCI false -firstHasOwnBookUCI true -firstTimeOdds 1 "
"-firstInitString \"" INIT_STRING "\" -firstComputerString \"" COMPUTER_STRING "\" "
"-firstFeatures \"\" -firstLogo \"\" -firstAccumulateTC 1 "
if(nickName[0]) snprintf(buf, MSG_SIZ, "\"%s\" -fcp ", nickName); else buf[0] = NULLCHAR;
quote = strchr(p, '"') ? '\'' : '"'; // use single quotes around engine command if it contains double quotes
snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), "%c%s%c -fd \"%s\"%s%s%s%s%s%s%s%s\n",
- quote, p, quote, appData.directory[i],
+ quote, p, quote, appData.directory[i],
useNick ? " -fn \"" : "",
useNick ? nickName : "",
useNick ? "\"" : "",
if(mps)
snprintf(buf, MSG_SIZ, ":%d/%s+%g", mps, mytc, ti);
- else
+ else
snprintf(buf, MSG_SIZ, ":%s+%g", mytc, ti);
} else {
if(mps)
snprintf(buf, MSG_SIZ, ":%d/%s", mps, mytc);
- else
+ else
snprintf(buf, MSG_SIZ, ":%s", mytc);
}
fullTimeControlString = StrSave(buf); // this should now be in PGN format
-
+
if( NextTimeControlFromString( &tc, &tc1 ) != 0 ) {
return FALSE;
}
Boolean valid;
int nr = 0;
- if (gameMode == AnalyzeMode && currentMove < forwardMostMove) {
+ lastParseAttempt = pv; if(!*pv) return; // turns out we crash when we parse an empty PV
+ if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && currentMove < forwardMostMove) {
PushInner(currentMove, forwardMostMove); // [HGM] engine might not be thinking on forwardMost position!
pushed = TRUE;
}
static char buf[10*MSG_SIZ];
int i, k=0, savedEnd=endPV, saveFMM = forwardMostMove;
*buf = NULLCHAR;
- if(forwardMostMove < endPV) PushInner(forwardMostMove, endPV);
+ if(forwardMostMove < endPV) PushInner(forwardMostMove, endPV); // shelve PV of PV-walk
ParsePV(pv, FALSE, 2); // this appends PV to game, suppressing any display of it
for(i = forwardMostMove; i<endPV; i++){
if(i&1) snprintf(buf+k, 10*MSG_SIZ-k, "%s ", parseList[i]);
k += strlen(buf+k);
}
snprintf(buf+k, 10*MSG_SIZ-k, "%s", lastParseAttempt); // if we ran into stuff that could not be parsed, print it verbatim
+ if(pushed) { PopInner(0); pushed = FALSE; } // restore game continuation shelved by ParsePV
if(forwardMostMove < savedEnd) { PopInner(0); forwardMostMove = saveFMM; } // PopInner would set fmm to endPV!
endPV = savedEnd;
return buf;
initialPosition[2][0] = BlackAngel;
initialPosition[6][BOARD_WIDTH-1] = WhiteMarshall;
initialPosition[5][BOARD_WIDTH-1] = WhiteAngel;
- initialPosition[1][1] = initialPosition[2][1] =
+ initialPosition[1][1] = initialPosition[2][1] =
initialPosition[6][BOARD_WIDTH-2] = initialPosition[5][BOARD_WIDTH-2] = 1;
}
if (appData.debugMode) {
}
Boolean
-OnlyMove (int *x, int *y, Boolean captures)
+OnlyMove (int *x, int *y, Boolean captures)
{
DisambiguateClosure cl;
if (appData.zippyPlay || !appData.testLegality) return FALSE;
if( (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && fromY != DROP_RANK ) {
if( pup != EmptySquare ) return;
moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
- if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
+ if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
// holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
- while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++;
+ while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++;
fromY = DROP_RANK;
}
return;
}
doubleClick = FALSE;
- if(gameMode == AnalyzeMode && pausing && first.excludeMoves) { // use pause state to exclude moves
+ if(gameMode == AnalyzeMode && (pausing || controlKey) && first.excludeMoves) { // use pause state to exclude moves
doubleClick = TRUE; gatingPiece = boards[currentMove][y][x];
}
fromX = x; fromY = y; toX = toY = -1;
}
}
if(x == fromX && y == fromY) return; // if OnlyMove altered (x,y) we go on
- second = FALSE;
+ second = FALSE;
}
// ignore clicks on holdings
if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
|| majors + (12*pCnt[BlackFerz-side] | 6*pCnt[BlackAlfil-side]) > 16; // KCKAA, KCKAX, KCKEEX, KCKEXX (XX!=HH), KCKXXX
// TO DO: cases wih an unpromoted f-Pawn acting as platform for an opponent Cannon
+ } else if(v == VariantKnightmate) {
+ if(nMine == 1) return FALSE;
+ if(nMine == 2 && nHis == 1 && pCnt[WhiteBishop+side] + pCnt[WhiteFerz+side] + pCnt[WhiteKnight+side]) return FALSE; // KBK is only draw
} else if(pCnt[WhiteKing] == 1 && pCnt[BlackKing] == 1) { // other variants with orthodox Kings
int nBishops = pCnt[WhiteBishop+side] + pCnt[WhiteFerz+side];
// In any case it determnes if the game is a claimable draw (filling in EP_STATUS).
// Actually ending the game is now based on the additional internal condition canAdjudicate.
// Only when the game is ended, and the opponent is a computer, this opponent gets the move relayed.
- int k, count = 0; static int bare = 1;
+ int k, drop, count = 0; static int bare = 1;
ChessProgramState *engineOpponent = (gameMode == TwoMachinesPlay ? cps->other : (cps ? NULL : &first));
Boolean canAdjudicate = !appData.icsActive;
/* Check for rep-draws */
count = 0;
+ drop = gameInfo.holdingsSize && (gameInfo.variant != VariantSuper && gameInfo.variant != VariantSChess
+ && gameInfo.variant != VariantGreat && gameInfo.variant != VariantGrand);
for(k = forwardMostMove-2;
- k>=backwardMostMove && k>=forwardMostMove-100 &&
+ k>=backwardMostMove && k>=forwardMostMove-100 && (drop ||
(signed char)boards[k][EP_STATUS] < EP_UNKNOWN &&
- (signed char)boards[k+2][EP_STATUS] <= EP_NONE && (signed char)boards[k+1][EP_STATUS] <= EP_NONE;
+ (signed char)boards[k+2][EP_STATUS] <= EP_NONE && (signed char)boards[k+1][EP_STATUS] <= EP_NONE);
k-=2)
{ int rights=0;
if(CompareBoards(boards[k], boards[forwardMostMove])) {
if(cps->initDone) return FALSE;
cps->isr = NULL; // this should suppress further error popups from breaking pipes
DestroyChildProcess(cps->pr, 9 ); // just to be sure
- cps->pr = NoProc;
+ cps->pr = NoProc;
if(cps == &first) {
appData.noChessProgram = TRUE;
gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu
}
static int savedWhitePlayer, savedBlackPlayer, pairingReceived;
+static ChessProgramState *stalledEngine;
+static char stashedInputMove[MSG_SIZ];
void
HandleMachineMove (char *message, ChessProgramState *cps)
if ((sscanf(message, "%s %s %s", buf1, buf2, machineMove) == 3 && strcmp(buf2, "...") == 0) ||
(sscanf(message, "%s %s", buf1, machineMove) == 2 && strcmp(buf1, "move") == 0))
{
+ if(pausing && !cps->pause) { // for pausing engine that does not support 'pause', we stash its move for processing when we resume.
+ if(appData.debugMode) fprintf(debugFP, "pause %s engine after move\n", cps->which);
+ safeStrCpy(stashedInputMove, message, MSG_SIZ);
+ stalledEngine = cps;
+ if(appData.ponderNextMove) { // bring opponent out of ponder
+ if(gameMode == TwoMachinesPlay) {
+ if(cps->other->pause)
+ PauseEngine(cps->other);
+ else
+ SendToProgram("easy\n", cps->other);
+ }
+ }
+ StopClocks();
+ return;
+ }
+
/* This method is only useful on engines that support ping */
if (cps->lastPing != cps->lastPong) {
if (gameMode == BeginningOfGame) {
return; // [HGM] This return was missing, causing option features to be recognized as non-compliant commands!
}
- if ((!appData.testLegality || gameInfo.variant == VariantFairy) &&
+ if ((!appData.testLegality || gameInfo.variant == VariantFairy) &&
!strncmp(message, "setup ", 6)) { // [HGM] allow first engine to define opening position
int dummy, s=6; char buf[MSG_SIZ];
if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
) {
/* white pawn promotion */
board[toY][toX] = CharToPiece(ToUpper(promoChar));
- if(gameInfo.variant==VariantBughouse ||
- gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */
+ if((gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse)
+ && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */
board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);
board[fromY][fromX] = EmptySquare;
} else if ((fromY >= BOARD_HEIGHT>>1)
) {
/* black pawn promotion */
board[toY][toX] = CharToPiece(ToLower(promoChar));
- if(gameInfo.variant==VariantBughouse ||
- gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */
+ if((gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse)
+ && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */
board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);
board[fromY][fromX] = EmptySquare;
} else if ((fromY < BOARD_HEIGHT>>1)
if (instant) return;
DisplayMove(currentMove - 1);
- DrawPosition(FALSE, boards[currentMove]);
if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile) {
if (appData.highlightLastMove) { // [HGM] moved to after DrawPosition, as with arrow it could redraw old board
SetHighlights(fromX, fromY, toX, toY);
}
}
+ DrawPosition(FALSE, boards[currentMove]);
DisplayBothClocks();
HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
}
fprintf(f, "-loadPositionFile \"%s\"\n", appData.loadPositionFile);
fprintf(f, "-loadPositionIndex %d\n", appData.loadPositionIndex);
fprintf(f, "-rewindIndex %d\n", appData.rewindIndex);
+ fprintf(f, "-usePolyglotBook %s\n", appData.usePolyglotBook ? "true" : "false");
+ fprintf(f, "-polyglotBook %s\n", appData.polyglotBook);
+ fprintf(f, "-bookDepth %d\n", appData.bookDepth);
+ fprintf(f, "-bookVariation %d\n", appData.bookStrength);
fprintf(f, "-discourageOwnBooks %s\n", appData.defNoBook ? "true" : "false");
+ fprintf(f, "-defaultHashSize %d\n", appData.defaultHashSize);
+ fprintf(f, "-defaultCacheSizeEGTB %d\n", appData.defaultCacheSizeEGTB);
+ fprintf(f, "-ponderNextMove %s\n", appData.ponderNextMove ? "true" : "false");
+ fprintf(f, "-smpCores %d\n", appData.smpCores);
if(searchTime > 0)
fprintf(f, "-searchTime \"%d:%02d\"\n", searchTime/60, searchTime%60);
else {
*blackPlayer = curRound + appData.tourneyType;
}
- // take care of white/black alternation per round.
+ // take care of white/black alternation per round.
// For cycles and games this is already taken care of by default, derived from matchGame!
return curRound & 1;
}
SendToProgram(buf, &pairing);
return 0; // wait for pairing engine to answer (which causes NextTourneyGame to be called again...
}
- pairingReceived = 0; // ... so we continue here
+ pairingReceived = 0; // ... so we continue here
*swapColors = 0;
appData.matchGames = appData.tourneyCycles * syncInterval - 1;
whitePlayer = savedWhitePlayer-1; blackPlayer = savedBlackPlayer-1;
fromX = fromY = -1; // [HGM] abort any move the user is entering.
+ if(pausing) PauseEvent(); // can happen when we abort a paused game (New Game or Quit)
+
if (appData.icsActive && (whosays == GE_ENGINE || whosays >= GE_ENGINE1)) {
/* If we are playing on ICS, the server decides when the
game is over, but the engine can offer to draw, claim
&& lastSavedGame != GameCheckSum() // [HGM] save: suppress duplicates
) {
if (*appData.saveGameFile != NULLCHAR) {
+ if(result == GameUnfinished && matchMode && *appData.tourneyFile)
+ AutoSaveGame(); // [HGM] protect tourney PGN from aborted games, and prompt for name instead
+ else
SaveGameToFile(appData.saveGameFile, TRUE);
} else if (appData.autoSaveGames) {
AutoSaveGame();
if(piece < BlackPawn) piece += BlackPawn; else if(piece < EmptySquare) piece -= BlackPawn; // color-flip
reverseBoard[r][f] = piece;
}
- reverseBoard[EP_STATUS-1] = soughtBoard[EP_STATUS-1] ^ 3;
+ reverseBoard[EP_STATUS-1] = soughtBoard[EP_STATUS-1] ^ 3;
for(r=0; r<6; r++) reverseBoard[CASTLING][r] = boards[currentMove][CASTLING][(r+3)%6];
if(appData.findMirror && appData.searchMode <= 3 && (!nrCastlingRights
- || (boards[currentMove][CASTLING][2] == NoRights ||
+ || (boards[currentMove][CASTLING][2] == NoRights ||
boards[currentMove][CASTLING][0] == NoRights && boards[currentMove][CASTLING][1] == NoRights )
- && (boards[currentMove][CASTLING][5] == NoRights ||
+ && (boards[currentMove][CASTLING][5] == NoRights ||
boards[currentMove][CASTLING][3] == NoRights && boards[currentMove][CASTLING][4] == NoRights ) )
) {
flipSearch = TRUE;
if (oldGameMode == AnalyzeFile ||
oldGameMode == AnalyzeMode) {
appData.loadGameIndex = -1; // [HGM] order auto-stepping through games
- keepInfo = 1;
AnalyzeFileEvent();
- keepInfo = 0;
}
if(creatingBook) return TRUE;
}
void
+PauseEngine (ChessProgramState *cps)
+{
+ SendToProgram("pause\n", cps);
+ cps->pause = 2;
+}
+
+void
+UnPauseEngine (ChessProgramState *cps)
+{
+ SendToProgram("resume\n", cps);
+ cps->pause = 1;
+}
+
+void
PauseEvent ()
{
if (appData.debugMode)
if (pausing) {
pausing = FALSE;
ModeHighlight();
+ if(stalledEngine) { // [HGM] pause: resume game by releasing withheld move
+ StartClocks();
+ if(gameMode == TwoMachinesPlay) { // we might have to make the opponent resume pondering
+ if(stalledEngine->other->pause == 2) UnPauseEngine(stalledEngine->other);
+ else if(appData.ponderNextMove) SendToProgram("hard\n", stalledEngine->other);
+ }
+ if(appData.ponderNextMove) SendToProgram("hard\n", stalledEngine);
+ HandleMachineMove(stashedInputMove, stalledEngine);
+ stalledEngine = NULL;
+ return;
+ }
if (gameMode == MachinePlaysWhite ||
- gameMode == MachinePlaysBlack) {
+ gameMode == TwoMachinesPlay ||
+ gameMode == MachinePlaysBlack) { // the thinking engine must have used pause mode, or it would have been stalledEngine
+ if(first.pause) UnPauseEngine(&first);
+ else if(appData.ponderNextMove) SendToProgram("hard\n", &first);
+ if(second.pause) UnPauseEngine(&second);
+ else if(gameMode == TwoMachinesPlay && appData.ponderNextMove) SendToProgram("hard\n", &second);
StartClocks();
} else {
DisplayBothClocks();
Reset(FALSE, TRUE);
SendToICS(ics_prefix);
SendToICS("refresh\n");
- } else if (currentMove < forwardMostMove) {
+ } else if (currentMove < forwardMostMove && gameMode != AnalyzeMode) {
ForwardInner(forwardMostMove);
}
pauseExamInvalid = FALSE;
case TwoMachinesPlay:
if (forwardMostMove == 0)
return; /* don't pause if no one has moved */
- if ((gameMode == MachinePlaysWhite &&
- !WhiteOnMove(forwardMostMove)) ||
- (gameMode == MachinePlaysBlack &&
- WhiteOnMove(forwardMostMove))) {
+ if(gameMode == TwoMachinesPlay) { // [HGM] pause: stop clocks if engine can be paused immediately
+ ChessProgramState *onMove = (WhiteOnMove(forwardMostMove) == (first.twoMachinesColor[0] == 'w') ? &first : &second);
+ if(onMove->pause) { // thinking engine can be paused
+ PauseEngine(onMove); // do it
+ if(onMove->other->pause) // pondering opponent can always be paused immediately
+ PauseEngine(onMove->other);
+ else
+ SendToProgram("easy\n", onMove->other);
+ StopClocks();
+ } else if(appData.ponderNextMove) SendToProgram("easy\n", onMove); // pre-emptively bring out of ponder
+ } else if(gameMode == (WhiteOnMove(forwardMostMove) ? MachinePlaysWhite : MachinePlaysBlack)) { // engine on move
+ if(first.pause) {
+ PauseEngine(&first);
+ StopClocks();
+ } else if(appData.ponderNextMove) SendToProgram("easy\n", &first); // pre-emptively bring out of ponder
+ } else { // human on move, pause pondering by either method
+ if(first.pause)
+ PauseEngine(&first);
+ else if(appData.ponderNextMove)
+ SendToProgram("easy\n", &first);
StopClocks();
}
+ // if no immediate pausing is possible, wait for engine to move, and stop clocks then
case AnalyzeMode:
pausing = TRUE;
ModeHighlight();
}
if (gameMode != AnalyzeMode) {
+ keepInfo = 1; // mere annotating should not alter PGN tags
EditGameEvent();
+ keepInfo = 0;
if (gameMode != EditGame) return;
if (!appData.showThinking) ToggleShowThinking();
ResurrectChessProgram();
gameMode = AnalyzeFile;
pausing = FALSE;
ModeHighlight();
- SetGameInfo();
StartAnalysisClock();
GetTimeMark(&lastNodeCountTime);
gameInfo.white, _("vs."), gameInfo.black,
nextGame+1, appData.matchGames+1,
appData.tourneyType>0 ? "gt" : appData.tourneyType<0 ? "sw" : "rr");
- } else
+ } else
if (first.twoMachinesColor[0] == 'w') {
snprintf(buf, MSG_SIZ, "%s %s %s (%d-%d-%d)",
gameInfo.white, _("vs."), gameInfo.black,
for(i=target; i>backwardMostMove; i--) { // seek back to start or previous null move
if(moveList[i-1][1] == '@' && moveList[i-1][0] == '@') break;
}
- SendBoard(&first, i);
+ SendBoard(&first, i);
if(second.analyzing) SendBoard(&second, i);
for(currentMove=i; currentMove<target; currentMove++) {
SendMoveToProgram(currentMove, &first);
char *p;
float score;
- if(index && sscanf(text, "%f/%d", &score, &len) == 2 &&
+ if(index && sscanf(text, "%f/%d", &score, &len) == 2 &&
pvInfoList[index-1].depth == len &&
fabs(pvInfoList[index-1].score - score*100.) < 0.5 &&
(p = strchr(text, '\n'))) text = p; // [HGM] strip off first line with PV info, if any
sscanf(message, "tell%c", &c)!=1 && sscanf(message, "0-1 %c", &c)!=1 &&
sscanf(message, "1-0 %c", &c)!=1 && sscanf(message, "1/2-1/2 %c", &c)!=1 &&
sscanf(message, "setboard %c", &c)!=1 && sscanf(message, "setup %c", &c)!=1 &&
- sscanf(message, "hint: %c", &c)!=1 &&
+ sscanf(message, "hint: %c", &c)!=1 &&
sscanf(message, "pong %c", &c)!=1 && start != '#') {
quote = appData.engineComments == 2 ? "# " : "### NON-COMPLIANT! ### ";
print = (appData.engineComments >= 2);
if (BoolFeature(&p, "exclude", &cps->excludeMoves, cps)) continue;
if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue;
if (BoolFeature(&p, "name", &cps->sendName, cps)) continue;
- if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */
+ if (BoolFeature(&p, "pause", &cps->pause, cps)) continue; // [HGM] pause
if (IntFeature(&p, "done", &val, cps)) {
FeatureDone(cps, val);
continue;
void
TypeInEvent (char firstChar)
{
- if ((gameMode == BeginningOfGame && !appData.icsActive) ||
+ if ((gameMode == BeginningOfGame && !appData.icsActive) ||
gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||
- gameMode == AnalyzeMode || gameMode == EditGame ||
+ gameMode == AnalyzeMode || gameMode == EditGame ||
gameMode == EditPosition || gameMode == IcsExamining ||
gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
isdigit(firstChar) && // [HGM] movenum: allow typing in of move nr in 'passive' modes
return;
}
- if (gameMode != EditGame && currentMove != forwardMostMove &&
+ if (gameMode != EditGame && currentMove != forwardMostMove &&
gameMode != Training) {
DisplayMoveError(_("Displayed move is not current"));
} else {
- int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove,
+ int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove,
&moveType, &fromX, &fromY, &toX, &toY, &promoChar);
if(!ok && move[0] >= 'a') { move[0] += 'A' - 'a'; ok = 2; } // [HGM] try also capitalized
- if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove,
+ if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove,
&moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {
- UserMoveEvent(fromX, fromY, toX, toY, promoChar);
+ UserMoveEvent(fromX, fromY, toX, toY, promoChar);
} else {
DisplayMoveError(_("Could not parse move"));
}
snprintf(buf, MSG_SIZ, "\"%s\"", nickName);
if(appData.useBitmaps) {
snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt true -lbtf \"%s\" -dbtf \"%s\" -lbtm %d -dbtm %d",
- appData.liteBackTextureFile, appData.darkBackTextureFile,
+ appData.liteBackTextureFile, appData.darkBackTextureFile,
appData.liteBackTextureMode,
appData.darkBackTextureMode );
} else {