int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */
static int initPing = -1;
int border; /* [HGM] width of board rim, needed to size seek graph */
-char bestMove[MSG_SIZ];
+char bestMove[MSG_SIZ], avoidMove[MSG_SIZ];
int solvingTime, totalTime;
/* States for ics_getting_history */
}
matchMode = mode;
matchGame = roundNr = 1;
- first.matchWins = second.matchWins = 0; // [HGM] match: needed in later matches
+ first.matchWins = second.matchWins = totalTime = 0; // [HGM] match: needed in later matches
NextMatchGame();
}
#if ZIPPY
if (loggedOn == TRUE)
if (ZippyControl(buf, &backup) || ZippyConverse(buf, &backup) ||
- (appData.zippyPlay && ZippyMatch(buf, &backup)));
+ (appData.zippyPlay && ZippyMatch(buf, &backup)))
+ ;
#endif
} // [DM] 'else { ' deleted
if (
ChessMove lastLoadGameStart = EndOfFile;
int doubleClick;
Boolean addToBookFlag;
+static Board rightsBoard, nullBoard;
void
UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar)
if(!appData.pieceMenu && toX == fromX && toY == fromY && boards[0][rf][ff] != EmptySquare) {
ChessSquare p = boards[0][rf][ff];
if(PieceToChar(p) == '+') gatingPiece = CHUDEMOTED(p); else
- if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p);
+ if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p); else
+ if(p == WhiteKing || p == BlackKing || p == WhiteRook || p == BlackRook) {
+ int n = rightsBoard[toY][toX] ^= 1; // toggle virginity of K or R
+ DisplayMessage("", n ? _("rights granted") : _("rights revoked"));
+ gatingPiece = p;
+ }
}
boards[0][toY][toX] = boards[0][fromY][fromX];
+ rightsBoard[toY][toX] = 0; // revoke rights on moving
if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings
if(boards[0][fromY][0] != EmptySquare) {
if(boards[0][fromY][1]) boards[0][fromY][1]--;
if(ExcludeOneMove(fromY, fromX, toY, toX, promoChar, '*')) // toggle
ClearPremoveHighlights(); // was included
else ClearHighlights(), SetPremoveHighlights(ff, rf, ft, rt); // exclusion indicated by premove highlights
+ DrawPosition(FALSE, NULL);
return;
}
flashing = 1; // prevent recursive calling (by release of to-click) while flashing piece
UserMoveEvent(fromX, fromY, toX, toY, promoChoice);
if (!appData.highlightLastMove || gotPremove) ClearHighlights();
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
+ if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY), DrawPosition(FALSE, NULL);
if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed
Explode(boards[currentMove-1], fromX, fromY, toX, toY))
DrawPosition(TRUE, boards[currentMove]);
}
if(appData.epd) {
if(solvingTime >= 0) {
- snprintf(buf1, MSG_SIZ, "%d. solved %4.2fs\n", matchGame, solvingTime/100.);
- totalTime += solvingTime; first.matchWins++;
+ snprintf(buf1, MSG_SIZ, "%d. %4.2fs: %s ", matchGame, solvingTime/100., parseList[backwardMostMove]);
+ totalTime += solvingTime; first.matchWins++; solvingTime = -1;
} else {
- snprintf(buf1, MSG_SIZ, "%d. wrong (%s)\n", matchGame, parseList[backwardMostMove]);
- second.matchWins++;
+ snprintf(buf1, MSG_SIZ, "%d. %s?%s ", matchGame, parseList[backwardMostMove], solvingTime == -2 ? " ???" : "");
+ if(solvingTime == -2) second.matchWins++;
}
OutputKibitz(2, buf1);
GameEnds(GameUnfinished, NULL, GE_XBOARD);
if(initPing == cps->lastPong) {
if(gameInfo.variant == VariantUnknown) {
DisplayError(_("Engine did not send setup for non-standard variant"), 0);
- *engineVariant = NULLCHAR; appData.variant = VariantNormal; // back to normal as error recovery?
+ *engineVariant = NULLCHAR; ASSIGN(appData.variant, "normal"); // back to normal as error recovery?
GameEnds(GameUnfinished, NULL, GE_XBOARD);
}
initPing = -1;
if (!ignore) {
ChessProgramStats tempStats = programStats; // [HGM] info: filter out info lines
+ int solved = 0;
buf1[0] = NULLCHAR;
if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",
&plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) {
if(*bestMove) { // rememer time best EPD move was first found
int ff1, tf1, fr1, tr1, ff2, tf2, fr2, tr2; char pp1, pp2;
- ChessMove mt;
- int ok = ParseOneMove(bestMove, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1);
- ok &= ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2);
- solvingTime = (ok && ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2 ? time : -1);
+ ChessMove mt; char *p = bestMove;
+ int ok = ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2);
+ solved = 0;
+ while(ok && *p && ParseOneMove(p, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1)) {
+ if(ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2) {
+ solvingTime = (solvingTime < 0 ? time : solvingTime);
+ solved = 1;
+ break;
+ }
+ while(*p && *p != ' ') p++;
+ while(*p == ' ') p++;
+ }
+ if(!solved) solvingTime = -1;
+ }
+ if(*avoidMove && !solved) {
+ int ff1, tf1, fr1, tr1, ff2, tf2, fr2, tr2; char pp1, pp2;
+ ChessMove mt; char *p = avoidMove, solved = 1;
+ int ok = ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2);
+ while(ok && *p && ParseOneMove(p, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1)) {
+ if(ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2) {
+ solved = 0; solvingTime = -2;
+ break;
+ }
+ while(*p && *p != ' ') p++;
+ while(*p == ' ') p++;
+ }
+ if(solved && !*bestMove) solvingTime = (solvingTime < 0 ? time : solvingTime);
}
if(serverMoves && (time > 100 || time == 0 && plylev > 7)) {
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
- for(rookX=fromX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT-1; rookX++); // castle with nearest piece
+ for(rookX=fromX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT-1; rookX++)
+ ; // castle with nearest piece
board[fromY][toX-1] = board[fromY][rookX];
board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX < fromX-1) {
- for(rookX=fromX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--); // castle with nearest piece
+ for(rookX=fromX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--)
+ ; // castle with nearest piece
board[fromY][toX+1] = board[fromY][rookX];
board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
- for(rookX=toX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT - 1; rookX++);
+ for(rookX=toX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT - 1; rookX++)
+ ;
board[fromY][toX-1] = board[fromY][rookX];
board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX < fromX-1) {
- for(rookX=toX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--);
+ for(rookX=toX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--)
+ ;
board[fromY][toX+1] = board[fromY][rookX];
board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
p++; q++;
}
if(*p) { // difference
- while(*p && *p++ != '\n');
- while(*q && *q++ != '\n');
+ while(*p && *p++ != '\n')
+ ;
+ while(*q && *q++ != '\n')
+ ;
changed = nPlayers;
changes = 1 + (strcmp(p, q) != 0);
}
return;
} else {
gameMode = nextGameMode;
+ if(appData.epd) {
+ snprintf(buf, MSG_SIZ, "-------------------------------------- ");
+ OutputKibitz(2, buf);
+ snprintf(buf, MSG_SIZ, _("Average solving time %4.2f sec (total time %4.2f sec) "), totalTime/(100.*first.matchWins), totalTime/100.);
+ OutputKibitz(2, buf);
+ snprintf(buf, MSG_SIZ, _("%d avoid-moves played "), second.matchWins);
+ if(second.matchWins) OutputKibitz(2, buf);
+ snprintf(buf, MSG_SIZ, _("Solved %d out of %d (%3.1f%%) "), first.matchWins, nextGame-1, first.matchWins*100./(nextGame-1));
+ OutputKibitz(2, buf);
+ }
snprintf(buf, MSG_SIZ, _("Match %s vs. %s: final score %d-%d-%d"),
first.tidy, second.tidy,
first.matchWins, second.matchWins,
return FALSE;
}
if((strchr(line, ';')) && (p = strstr(line, " bm "))) { // EPD with best move
- sscanf(p+4, "%s", bestMove);
+ sscanf(p+4, "%[^;]", bestMove);
} else *bestMove = NULLCHAR;
+ if((strchr(line, ';')) && (p = strstr(line, " am "))) { // EPD with avoid move
+ sscanf(p+4, "%[^;]", avoidMove);
+ } else *avoidMove = NULLCHAR;
} else {
(void) fgets(line, MSG_SIZ, f);
(void) fgets(line, MSG_SIZ, f);
ScheduleDelayedEvent(TwoMachinesEventIfReady, 10);
return;
}
+ if(!appData.epd) {
if(WaitForEngine(&second, TwoMachinesEventIfReady)) return; // (if needed:) started up second engine, so wait for features
if(!SupportedVariant(second.variants, gameInfo.variant, gameInfo.boardWidth,
ScheduleDelayedEvent(TwoMachinesEventIfReady, 10);
return;
}
+ }
GetTimeMark(&now); // [HGM] matchpause: implement match pause after engine load
if(appData.matchPause>10000 || appData.matchPause<10)
appData.matchPause = 10000; /* [HGM] make pause adjustable */
// we are now committed to starting the game
stalling = 0;
DisplayMessage("", "");
+ if(!appData.epd) {
if (startedFromSetupPosition) {
SendBoard(&second, backwardMostMove);
if (appData.debugMode) {
for (i = backwardMostMove; i < forwardMostMove; i++) {
SendMoveToProgram(i, &second);
}
+ }
gameMode = TwoMachinesPlay;
pausing = startingEngine = FALSE;
snprintf(buf, MSG_SIZ, "name %s\n", second.tidy);
SendToProgram(buf, &first);
}
+ if(!appData.epd) {
SendToProgram(second.computerString, &second);
if (second.sendName) {
snprintf(buf, MSG_SIZ, "name %s\n", first.tidy);
SendToProgram(buf, &second);
}
+ }
ResetClocks();
if (!first.sendTime || !second.sendTime) {
SetGameInfo();
}
-
void
EditPositionEvent ()
{
+ int i;
if (gameMode == EditPosition) {
EditGameEvent();
return;
gameMode = EditPosition;
ModeHighlight();
SetGameInfo();
+ CopyBoard(rightsBoard, nullBoard);
if (currentMove > 0)
CopyBoard(boards[0], boards[currentMove]);
+ for(i=0; i<nrCastlingRights; i++) if(boards[0][CASTLING][i] != NoRights)
+ rightsBoard[castlingRank[i]][boards[0][CASTLING][i]] = 1; // copy remaining rights
blackPlaysFirst = !WhiteOnMove(currentMove);
ResetClocks();
ChessSquare piece = boards[0][y][x];
static Board erasedBoard, currentBoard, menuBoard, nullBoard;
static int lastVariant;
+ int baseRank = BOARD_HEIGHT-1, hasRights = 0;
if (gameMode != EditPosition && gameMode != IcsExamining) return;
selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);
goto defaultlabel;
+ case WhiteRook:
+ baseRank = 0;
+ case BlackRook:
+ if(y == baseRank && (x == BOARD_LEFT || x == BOARD_RGHT-1 || appData.fischerCastling)) hasRights = 1;
+ goto defaultlabel;
+
case WhiteKing:
+ baseRank = 0;
case BlackKing:
if(gameInfo.variant == VariantXiangqi)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteWazir);
if(gameInfo.variant == VariantKnightmate)
selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteUnicorn);
+ if(y == baseRank && (x == BOARD_WIDTH>>1 || appData.fischerCastling)) hasRights = 1;
default:
defaultlabel:
if (gameMode == IcsExamining) {
PieceToChar(selection), AAA + x, ONE + y);
SendToICS(buf);
} else {
+ rightsBoard[y][x] = hasRights;
if(x < BOARD_LEFT || x >= BOARD_RGHT) {
int n;
if(x == BOARD_LEFT-2 && selection >= BlackPawn) {
pvInfoList[index-1].score = score;
pvInfoList[index-1].time = 10*time; // centi-sec
if(*sep == '}') *sep = 0; else *--sep = '{';
- if(p != text) { while(*p++ = *sep++); sep = text; } // squeeze out space between PV and comment, and return both
+ if(p != text) {
+ while(*p++ = *sep++)
+ ;
+ sep = text;
+ } // squeeze out space between PV and comment, and return both
}
return sep;
}
}
if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines
- while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p;
+ while(*p++ = *q++)
+ ;
+ if(q != overrideCastling+1) p[-1] = ' '; else --p;
} else {
if(haveRights) {
int handW=0, handB=0;