char*
safeStrCpy( char *dst, const char *src, size_t count )
-{
- /* see for example: https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/854-BSI.html
- *
- * usage: safeStrCpy( stringA, stringB, sizeof(stringA)/sizeof(stringA[0]);
- */
-
+{ // [HGM] made safe
+ int i;
assert( dst != NULL );
assert( src != NULL );
assert( count > 0 );
- strncpy( dst, src, count );
- if( dst[ count-1 ] != '\0' )
+ for(i=0; i<count; i++) if((dst[i] = src[i]) == NULLCHAR) break;
+ if( i == count-1 && dst[i] != NULLCHAR)
{
+ dst[ count-1 ] = '\0'; // make sure incomplete copy still null-terminated
if(appData.debugMode)
printf("safeStrCpy: copying %s into %s didn't work, not enough space %d\n",src,dst,count);
}
- dst[ count-1 ] = '\0';
return dst;
}
char white_holding[64], black_holding[64];
TimeMark lastNodeCountTime;
long lastNodeCount=0;
+int shiftKey; // [HGM] set by mouse handler
+
int have_sent_ICS_logon = 0;
+int sending_ICS_login = 0;
+int sending_ICS_password = 0;
+
int movesPerSession;
int suddenDeath, whiteStartMove, blackStartMove; /* [HGM] for implementation of 'any per time' sessions, as in first part of byoyomi TC */
long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement, lastWhite, lastBlack;
if(**str == '!') type = *(*str)++; // Bronstein TC
if(result = NextIntegerFromString( str, &temp2)) return -1;
*inc = temp2 * 1000;
+ if(**str == '.') { // read fraction of increment
+ char *start = ++(*str);
+ if(result = NextIntegerFromString( str, &temp2)) return -1;
+ temp2 *= 1000;
+ while(start++ < *str) temp2 /= 10;
+ *inc += temp2;
+ }
} else *inc = 0;
*moves = 0; *tc = temp * 1000; *incType = type;
return 0;
int
ParseTimeControl(tc, ti, mps)
char *tc;
- int ti;
+ float ti;
int mps;
{
long tc1;
long tc2;
char buf[MSG_SIZ], buf2[MSG_SIZ], *mytc = tc;
int min, sec=0;
- int len;
if(ti >= 0 && !strchr(tc, '+') && !strchr(tc, '/') ) mps = 0;
if(!strchr(tc, '+') && !strchr(tc, '/') && sscanf(tc, "%d:%d", &min, &sec) >= 1)
if(ti > 0) {
if(mps)
- snprintf(buf, MSG_SIZ, ":%d/%s+%d", mps, mytc, ti);
- else
- snprintf(buf, MSG_SIZ, ":%s+%d", mytc, ti);
+ snprintf(buf, MSG_SIZ, ":%d/%s+%g", mps, mytc, ti);
+ 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;
}
if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) {
ICSInitScript();
have_sent_ICS_logon = 1;
+ /* if we don't send the login/password via icsLogon, use special readline
+ code for it */
+ if (strlen(appData.icsLogon)==0)
+ {
+ sending_ICS_password = 0; // in case we come back to login
+ sending_ICS_login = 1;
+ };
continue;
}
+ /* need to shadow the password */
+ if (!sending_ICS_password && looking_at(buf, &i, "password:")) {
+ /* if we don't send the login/password via icsLogon, use special readline
+ code for it */
+ if (strlen(appData.icsLogon)==0)
+ sending_ICS_password = 1;
+ continue;
+ }
if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ &&
(looking_at(buf, &i, "\n<12> ") ||
/* [4] is " *" or empty (don't care). */
int gamenum = atoi(star_match[0]);
char *whitename, *blackname, *why, *endtoken;
- ChessMove endtype = (ChessMove) 0;
+ ChessMove endtype = EndOfFile;
if (tkind == 0) {
whitename = star_match[1];
}
if (gameInfo.boardHeight != ranks || gameInfo.boardWidth != files ||
- weird && (int)gameInfo.variant <= (int)VariantShogi) {
+ weird && (int)gameInfo.variant < (int)VariantShogi) {
/* [HGM] We seem to have switched variant unexpectedly
* Try to guess new variant from board size
*/
// So we parse the long-algebraic move string in stead of the SAN move
int valid; char buf[MSG_SIZ], *prom;
+ if(gameInfo.variant == VariantShogi && !strchr(move_str, '=') && !strchr(move_str, '@'))
+ strcat(move_str, "="); // if ICS does not say 'promote' on non-drop, we defer.
// str looks something like "Q/a1-a2"; kill the slash
if(str[1] == '/')
snprintf(buf, MSG_SIZ,"%c%s", str[0], str+2);
strcat(parseList[moveNum - 1], " ");
strcat(parseList[moveNum - 1], elapsed_time);
/* currentMoveString is set as a side-effect of ParseOneMove */
+ if(gameInfo.variant == VariantShogi && currentMoveString[4]) currentMoveString[4] = '^';
safeStrCpy(moveList[moveNum - 1], currentMoveString, sizeof(moveList[moveNum - 1])/sizeof(moveList[moveNum - 1][0]));
strcat(moveList[moveNum - 1], "\n");
+
+ if(gameInfo.holdingsWidth && !appData.disguise) // inherit info that ICS does not give from previous board
+ for(k=0; k<ranks; k++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) {
+ ChessSquare old, new = boards[moveNum][k][j];
+ if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
+ old = (k==toY && j==toX) ? boards[moveNum-1][fromY][fromX] : boards[moveNum-1][k][j]; // trace back mover
+ if(old == new) continue;
+ if(old == PROMOTED new) boards[moveNum][k][j] = old; // prevent promoted pieces to revert to primordial ones
+ else if(new == WhiteWazir || new == BlackWazir) {
+ if(old < WhiteCannon || old >= BlackPawn && old < BlackCannon)
+ boards[moveNum][k][j] = PROMOTED old; // choose correct type of Gold in promotion
+ else boards[moveNum][k][j] = old; // preserve type of Gold
+ } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!)
+ boards[moveNum][k][j] = PROMOTED new; // use non-primordial representation of chosen piece
+ }
} else {
/* Move from ICS was illegal!? Punt. */
if (appData.debugMode) {
break;
case WhiteNonPromotion:
case BlackNonPromotion:
- sprintf(user_move, "%c%c%c%c=\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY);
+ sprintf(user_move, "%c%c%c%c==\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY);
break;
case WhitePromotion:
case BlackPromotion:
break;
case WhiteDrop:
case BlackDrop:
+ drop:
snprintf(user_move, MSG_SIZ, "%c@%c%c\n",
- ToUpper(PieceToChar((ChessSquare) fromX)),
- AAA + toX, ONE + toY);
+ ToUpper(PieceToChar((ChessSquare) fromX)),
+ AAA + toX, ONE + toY);
break;
+ case IllegalMove: /* could be a variant we don't quite understand */
+ if(fromY == DROP_RANK) goto drop; // We need 'IllegalDrop' move type?
case NormalMove:
case WhiteCapturesEnPassant:
case BlackCapturesEnPassant:
- case IllegalMove: /* could be a variant we don't quite understand */
snprintf(user_move, MSG_SIZ,"%c%c%c%c\n",
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY);
break;
int *fromX, *fromY, *toX, *toY;
char *promoChar;
{
- if (appData.debugMode) {
- fprintf(debugFP, "move to parse: %s\n", move);
- }
*moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
switch (*moveType) {
case AmbiguousMove:
case ImpossibleMove:
- case (ChessMove) 0: /* end of file */
+ case EndOfFile:
case ElapsedTime:
case Comment:
case PGNTag:
/* Kludge to set black to move, avoiding the troublesome and now
* deprecated "black" command.
*/
- if (!WhiteOnMove(moveNum)) SendToProgram("a2a3\n", cps);
+ if (!WhiteOnMove(moveNum)) // [HGM] but better a deprecated command than an illegal move...
+ SendToProgram(boards[0][1][BOARD_LEFT] == WhitePawn ? "a2a3\n" : "black\n", cps);
SendToProgram("edit\n", cps);
SendToProgram("#\n", cps);
*promoChoice = PieceToChar(BlackFerz); // no choice
return FALSE;
}
+ // no sense asking what we must promote to if it is going to explode...
+ if(gameInfo.variant == VariantAtomic && boards[currentMove][toY][toX] != EmptySquare) {
+ *promoChoice = PieceToChar(BlackQueen); // Queen as good as any
+ return FALSE;
+ }
if(autoQueen) { // predetermined
if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantLosers)
*promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want
gameMode == IcsPlayingBlack && WhiteOnMove(currentMove);
if(appData.testLegality && !premove) {
moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
- fromY, fromX, toY, toX, NULLCHAR);
+ fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '+' : NULLCHAR);
if(moveType != WhitePromotion && moveType != BlackPromotion)
return FALSE;
}
case IcsPlayingBlack:
if(WhiteOnMove(currentMove)) return FALSE;
break;
+ case EditGame:
+ break;
default:
return FALSE;
}
int lastLoadGameNumber = 0, lastLoadPositionNumber = 0;
int lastLoadGameUseList = FALSE;
char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
-ChessMove lastLoadGameStart = (ChessMove) 0;
+ChessMove lastLoadGameStart = EndOfFile;
void
UserMoveEvent(fromX, fromY, toX, toY, promoChar)
pup = boards[currentMove][toY][toX];
/* [HGM] If move started in holdings, it means a drop. Convert to standard form */
- if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
+ if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
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;
}
the previous line in Analysis Mode */
if ((gameMode == AnalyzeMode || gameMode == EditGame)
&& currentMove < forwardMostMove) {
- PushTail(currentMove, forwardMostMove); // [HGM] vari: save tail of game
+ if(appData.variations && shiftKey) PushTail(currentMove, forwardMostMove); // [HGM] vari: save tail of game
+ else forwardMostMove = currentMove;
}
/* If we need the chess program but it's dead, restart it */
DrawPosition(TRUE, NULL);
}
+int
+Explode(Board board, int fromX, int fromY, int toX, int toY)
+{
+ if(gameInfo.variant == VariantAtomic &&
+ (board[toY][toX] != EmptySquare || // capture?
+ toX != fromX && (board[fromY][fromX] == WhitePawn || // e.p. ?
+ board[fromY][fromX] == BlackPawn )
+ )) {
+ AnimateAtomicCapture(board, fromX, fromY, toX, toY);
+ return TRUE;
+ }
+ return FALSE;
+}
+
void LeftClick(ClickType clickType, int xPix, int yPix)
{
int x, y;
}
PromotionPopUp();
} else {
+ int oldMove = currentMove;
UserMoveEvent(fromX, fromY, toX, toY, promoChoice);
if (!appData.highlightLastMove || gotPremove) ClearHighlights();
if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
+ if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed
+ Explode(boards[currentMove-1], fromX, fromY, toX, toY))
+ DrawPosition(TRUE, boards[currentMove]);
fromX = fromY = -1;
}
appData.animate = saveAnimate;
case EP_WINS:
result = WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins; break;
default:
- result = (ChessMove) 0;
+ result = EndOfFile;
}
if(canAdjudicate && appData.checkMates && result) { // [HGM] mates: adjudicate finished games if requested
if(engineOpponent)
return; // [HGM] This return was missing, causing option features to be recognized as non-compliant commands!
}
+ if (!appData.testLegality && !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 || startedFromSetupPosition) return;
+ if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
+ ParseFEN(boards[0], &dummy, message+s);
+ DrawPosition(TRUE, boards[0]);
+ startedFromSetupPosition = TRUE;
+ return;
+ }
/* [HGM] Allow engine to set up a position. Don't ask me why one would
* want this, I was asked to put it in, and obliged.
*/
yynewstr(game);
for (;;) {
yyboardindex = boardIndex;
- moveType = (ChessMove) yylex();
+ moveType = (ChessMove) Myylex();
switch (moveType) {
case IllegalMove: /* maybe suicide chess, etc. */
if (appData.debugMode) {
}
DisplayError(buf, 0);
return;
- case (ChessMove) 0: /* end of file */
+ case EndOfFile:
if (boardIndex < backwardMostMove) {
/* Oops, gap. How did that happen? */
DisplayError(_("Gap in move list"), 0);
if( board[toY][toX] != EmptySquare )
board[EP_STATUS] = EP_CAPTURE;
- /* [HGM] In Shatranj and Courier all promotions are to Ferz */
- if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
- && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
-
if (fromY == DROP_RANK) {
/* must be first */
piece = board[toY][toX] = (ChessSquare) fromX;
if(promoChar == '+') {
/* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */
board[toY][toX] = (ChessSquare) (PROMOTED piece);
- } else if(!appData.testLegality) { // without legality testing, unconditionally believe promoChar
- board[toY][toX] = CharToPiece(promoChar);
+ } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar
+ board[toY][toX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar));
}
- if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)
- && promoChar != NULLCHAR && gameInfo.holdingsSize) {
+ if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)
+ && promoChar != NULLCHAR && gameInfo.holdingsSize) {
// [HGM] superchess: take promotion piece out of holdings
int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
if((int)piece < (int)BlackPawn) { // determine stm from piece color
gotPremove = FALSE;
alarmSounded = FALSE;
- GameEnds((ChessMove) 0, NULL, GE_PLAYER);
+ GameEnds(EndOfFile, NULL, GE_PLAYER);
if(appData.serverMovesName != NULL) {
/* [HGM] prepare to make moves file for broadcasting */
clock_t t = clock();
}
yyboardindex = forwardMostMove;
- if (readAhead != (ChessMove)0) {
+ if (readAhead != EndOfFile) {
moveType = readAhead;
} else {
if (gameFileFP == NULL)
return FALSE;
- moveType = (ChessMove) yylex();
+ moveType = (ChessMove) Myylex();
}
done = FALSE;
}
break;
- case (ChessMove) 0: /* end of file */
+ case EndOfFile:
if (appData.debugMode)
fprintf(debugFP, "Parser hit end of file\n");
switch (MateTest(boards[currentMove], PosFlags(currentMove)) ) {
if (appData.debugMode)
fprintf(debugFP, "Parser ignoring: '%s' (%d)\n",
yy_text, (int) moveType);
- return LoadGameOneMove((ChessMove)0); /* tail recursion */
+ return LoadGameOneMove(EndOfFile); /* tail recursion */
}
/* else fall thru */
if (appData.debugMode)
fprintf(debugFP, "Parser ignoring: '%s' (%d)\n",
yy_text, (int) moveType);
- return LoadGameOneMove((ChessMove)0); /* tail recursion */
+ return LoadGameOneMove(EndOfFile); /* tail recursion */
case IllegalMove:
if (appData.testLegality) {
* 5-4-02: Let's try being more lenient and allowing a game to
* start with an unnumbered move. Does that break anything?
*/
- cm = lastLoadGameStart = (ChessMove) 0;
+ cm = lastLoadGameStart = EndOfFile;
while (gn > 0) {
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
switch (cm) {
- case (ChessMove) 0:
+ case EndOfFile:
if (cmailMsgLoaded) {
nCmailGames = CMAIL_MAX_GAMES - gn;
} else {
case PGNTag:
break;
case MoveNumberOne:
- case (ChessMove) 0:
+ case EndOfFile:
gn--; /* count this game */
lastLoadGameStart = cm;
break;
case GNUChessGame:
case PGNTag:
case MoveNumberOne:
- case (ChessMove) 0:
+ case EndOfFile:
gn--; /* count this game */
lastLoadGameStart = cm;
break;
if (gn > 0) {
do {
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
} while (cm == PGNTag || cm == Comment);
}
break;
case NormalMove:
/* Only a NormalMove can be at the start of a game
* without a position diagram. */
- if (lastLoadGameStart == (ChessMove) 0) {
+ if (lastLoadGameStart == EndOfFile ) {
gn--;
lastLoadGameStart = MoveNumberOne;
}
/* Skip any header junk before position diagram and/or move 1 */
for (;;) {
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
- if (cm == (ChessMove) 0 ||
+ if (cm == EndOfFile ||
cm == GNUChessGame || cm == XBoardGame) {
/* Empty game; pretend end-of-file and handle later */
- cm = (ChessMove) 0;
+ cm = EndOfFile;
break;
}
}
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
/* Handle comments interspersed among the tags */
while (cm == Comment) {
p = yy_text;
AppendComment(currentMove, p, FALSE);
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
}
}
}
}
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
}
if (first.pr == NoProc) {
p = yy_text;
AppendComment(currentMove, p, FALSE);
yyboardindex = forwardMostMove;
- cm = (ChessMove) yylex();
+ cm = (ChessMove) Myylex();
}
- if ((cm == (ChessMove) 0 && lastLoadGameStart != (ChessMove) 0) ||
+ if ((cm == EndOfFile && lastLoadGameStart != EndOfFile ) ||
cm == WhiteWins || cm == BlackWins ||
cm == GameIsDrawn || cm == GameUnfinished) {
DisplayMessage("", _("No moves in game"));
LoadGameOneMove(cm);
/* load the remaining moves from the file */
- while (LoadGameOneMove((ChessMove)0)) {
+ while (LoadGameOneMove(EndOfFile)) {
timeRemaining[0][forwardMostMove] = whiteTimeRemaining;
timeRemaining[1][forwardMostMove] = blackTimeRemaining;
}
}
void
+SettingsMenuIfReady()
+{
+ if (second.lastPing != second.lastPong) {
+ DisplayMessage("", _("Waiting for second chess program"));
+ ScheduleDelayedEvent(SettingsMenuIfReady, 10); // [HGM] fast: lowered from 1000
+ return;
+ }
+ ThawUI();
+ DisplayMessage("", "");
+ SettingsPopUp(&second);
+}
+
+int
+WaitForSecond(DelayedEventCallback retry)
+{
+ if (second.pr == NULL) {
+ StartChessProgram(&second);
+ if (second.protocolVersion == 1) {
+ retry();
+ } else {
+ /* kludge: allow timeout for initial "feature" command */
+ FreezeUI();
+ DisplayMessage("", _("Starting second chess program"));
+ ScheduleDelayedEvent(retry, FEATURE_TIMEOUT);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void
TwoMachinesEvent P((void))
{
int i;
TruncateGame(); // [HGM] vari: MachineWhite and MachineBlack do this...
ResurrectChessProgram(); /* in case first program isn't running */
- if (second.pr == NULL) {
- StartChessProgram(&second);
- if (second.protocolVersion == 1) {
- TwoMachinesEventIfReady();
- } else {
- /* kludge: allow timeout for initial "feature" command */
- FreezeUI();
- DisplayMessage("", _("Starting second chess program"));
- ScheduleDelayedEvent(TwoMachinesEventIfReady, FEATURE_TIMEOUT);
- }
- return;
- }
+ if(WaitForSecond(TwoMachinesEventIfReady)) return;
DisplayMessage("", "");
InitChessProgram(&second, FALSE);
SendToProgram("force\n", &second);
+ if(first.lastPing != first.lastPong) { // [HGM] wait till we are sure first engine has set up position
+ ScheduleDelayedEvent(TwoMachinesEvent, 10);
+ return;
+ }
if (startedFromSetupPosition) {
SendBoard(&second, backwardMostMove);
if (appData.debugMode) {
SendToProgram("force\n", &first);
break;
case TwoMachinesPlay:
- GameEnds((ChessMove) 0, NULL, GE_PLAYER);
+ GameEnds(EndOfFile, NULL, GE_PLAYER);
ResurrectChessProgram();
SetUserThinkingEnables();
break;
} else {
commentList[index] = (char *) malloc(len + 6); // perhaps wastes 4...
if(addBraces)
- safeStrCpy(commentList[index], "{\n", sizeof(commentList[index])/sizeof(commentList[index][0]));
+ safeStrCpy(commentList[index], "{\n", 3);
else commentList[index][0] = NULLCHAR;
strcat(commentList[index], text);
strcat(commentList[index], "\n");
/* Note old gnuchess bug -- minutes:seconds used to not work.
Fixed in later versions, but still avoid :seconds
when seconds is 0. */
- snprintf(buf, MSG_SIZ, "level %d %ld %d\n", mps, tc/60000, inc/1000);
+ snprintf(buf, MSG_SIZ, "level %d %ld %g\n", mps, tc/60000, inc/1000.);
} else {
- snprintf(buf, MSG_SIZ, "level %d %ld:%02d %d\n", mps, tc/60000,
- seconds, inc/1000);
+ snprintf(buf, MSG_SIZ, "level %d %ld:%02d %g\n", mps, tc/60000,
+ seconds, inc/1000.);
}
}
SendToProgram(buf, cps);
if(p && (p == cps->optionSettings || p[-1] == ',')) {
snprintf(buf, MSG_SIZ, "option %s", p);
if(p = strstr(buf, ",")) *p = 0;
+ if(q = strchr(buf, '=')) switch(opt->type) {
+ case ComboBox:
+ for(n=0; n<opt->max; n++)
+ if(!strcmp(((char**)opt->textValue)[n], q+1)) opt->value = n;
+ break;
+ case TextBox:
+ safeStrCpy(opt->textValue, q+1, MSG_SIZ - (opt->textValue - opt->name));
+ break;
+ case Spin:
+ case CheckBox:
+ opt->value = atoi(q+1);
+ default:
+ break;
+ }
strcat(buf, "\n");
SendToProgram(buf, cps);
}
{
DelayedEventCallback cb = GetDelayedEvent();
if ((cb == InitBackEnd3 && cps == &first) ||
+ (cb == SettingsMenuIfReady && cps == &second) ||
(cb == TwoMachinesEventIfReady && cps == &second)) {
CancelDelayedEvent();
ScheduleDelayedEvent(cb, val ? 1 : 3600000);
if (WhiteOnMove(forwardMostMove)) {
if(whiteNPS >= 0) lastTickLength = 0;
timeRemaining = whiteTimeRemaining -= lastTickLength;
- if(timeRemaining < 0) {
+ if(timeRemaining < 0 && !appData.icsActive) {
GetTimeQuota((forwardMostMove-whiteStartMove-1)/2, 0, whiteTC); // sets suddenDeath & nextSession;
if(suddenDeath) { // [HGM] if we run out of a non-last incremental session, go to the next
whiteStartMove = forwardMostMove; whiteTC = nextSession;
} else {
if(blackNPS >= 0) lastTickLength = 0;
timeRemaining = blackTimeRemaining -= lastTickLength;
- if(timeRemaining < 0) { // [HGM] if we run out of a non-last incremental session, go to the next
+ if(timeRemaining < 0 && !appData.icsActive) { // [HGM] if we run out of a non-last incremental session, go to the next
GetTimeQuota((forwardMostMove-blackStartMove-1)/2, 0, blackTC);
if(suddenDeath) {
blackStartMove = forwardMostMove;
while(*p==' ') p++;
if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {
if(*p == '[') p++;
- if(*p == '-' ) *p++; /* empty holdings */ else {
+ if(*p == '-' ) p++; /* empty holdings */ else {
if( !gameInfo.holdingsWidth ) return FALSE; /* no room to put holdings! */
/* if we would allow FEN reading to set board size, we would */
/* have to add holdings and shift the board read so far here */
while( (piece = CharToPiece(*p) ) != EmptySquare ) {
- *p++;
+ p++;
if((int) piece >= (int) BlackPawn ) {
i = (int)piece - (int)BlackPawn;
i = PieceToNumber((ChessSquare)i);
}
}
}
- if(*p == ']') *p++;
+ if(*p == ']') p++;
}
while(*p == ' ') p++;
char c = *p++ - AAA;
if(c < BOARD_LEFT || c >= BOARD_RGHT) return TRUE;
- if(*p >= '0' && *p <='9') *p++;
+ if(*p >= '0' && *p <='9') p++;
board[EP_STATUS] = c;
}
}
if(annotate) {
int cnt = 10;
if(!WhiteOnMove(currentMove))
- snprintf(buf, sizeof(buf)/sizeof(buf[0]),"(%d...", currentMove+2>>1);
+ snprintf(buf, sizeof(buf)/sizeof(buf[0]),"(%d...", (currentMove+2)>>1);
else safeStrCpy(buf, "(", sizeof(buf)/sizeof(buf[0]));
for(i=currentMove; i<forwardMostMove; i++) {
if(WhiteOnMove(i))
- snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0]), " %d. %s", i+2>>1, SavePart(parseList[i]));
+ snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0]), " %d. %s", (i+2)>>1, SavePart(parseList[i]));
else snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0])," %s", SavePart(parseList[i]));
strcat(buf, moveBuf);
if(commentList[i]) { strcat(buf, " "); strcat(buf, commentList[i]); }