} else
for (i=0; i<sizeof(variantNames)/sizeof(char*); i++) {
if (p = StrCaseStr(e, variantNames[i])) {
- if(p && i >= VariantShogi && (p != e || isalpha(p[strlen(variantNames[i])]))) continue;
+ if(p && i >= VariantShogi && (p != e && !appData.icsActive || isalpha(p[strlen(variantNames[i])]))) continue;
v = (VariantClass) i;
found = TRUE;
break;
static int savedWhitePlayer, savedBlackPlayer, pairingReceived;
static ChessProgramState *stalledEngine;
-static char stashedInputMove[MSG_SIZ];
+static char stashedInputMove[MSG_SIZ], abortEngineThink;
void
HandleMachineMove (char *message, ChessProgramState *cps)
return;
}
+ if(cps->usePing) {
+
/* This method is only useful on engines that support ping */
+ if(abortEngineThink) {
+ if (appData.debugMode) {
+ fprintf(debugFP, "Undoing move from aborted think of %s\n", cps->which);
+ }
+ SendToProgram("undo\n", cps);
+ return;
+ }
+
if (cps->lastPing != cps->lastPong) {
- if (gameMode == BeginningOfGame) {
/* Extra move from before last new; ignore */
if (appData.debugMode) {
fprintf(debugFP, "Ignoring extra move from %s\n", cps->which);
}
- } else {
- if (appData.debugMode) {
- fprintf(debugFP, "Undoing extra move from %s, gameMode %d\n",
- cps->which, gameMode);
- }
-
- SendToProgram("undo\n", cps);
- }
return;
}
+ } else {
+
switch (gameMode) {
case BeginningOfGame:
/* Extra move from before last reset; ignore */
}
return;
}
+ }
if(cps->alphaRank) AlphaRank(machineMove, 4);
}
initPing = -1;
}
+ if(cps->lastPing == cps->lastPong && abortEngineThink) {
+ abortEngineThink = FALSE;
+ DisplayMessage("", "");
+ ThawUI();
+ }
return;
}
if(!strncmp(message, "highlight ", 10)) {
case MachinePlaysBlack:
case BeginningOfGame:
SendToProgram("force\n", &first);
+ if(gameMode == (forwardMostMove & 1 ? MachinePlaysBlack : MachinePlaysWhite)) { // engine is thinking
+ if (first.usePing) { // [HGM] always send ping when we might interrupt machine thinking
+ char buf[MSG_SIZ];
+ abortEngineThink = TRUE;
+ snprintf(buf, MSG_SIZ, "ping %d\n", initPing = ++first.lastPing);
+ SendToProgram(buf, &first);
+ DisplayMessage("Aborting engine think", "");
+ FreezeUI();
+ }
+ }
SetUserThinkingEnables();
break;
case PlayFromGameFile:
PositionToFEN (int move, char *overrideCastling, int moveCounts)
{
int i, j, fromX, fromY, toX, toY;
- int whiteToPlay;
+ int whiteToPlay, haveRights = nrCastlingRights;
char buf[MSG_SIZ];
char *p, *q;
int emptycount;
*p++ = whiteToPlay ? 'w' : 'b';
*p++ = ' ';
+ if(pieceDesc[WhiteKing] && strchr(pieceDesc[WhiteKing], 'i') && !strchr(pieceDesc[WhiteKing], 'O')) { // redefined without castling
+ haveRights = 0; q = p;
+ for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) {
+ piece = boards[move][0][i];
+ if(piece >= WhitePawn && piece <= WhiteKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move
+ if(!(boards[move][TOUCHED_W] & 1<<i)) *p++ = 'A' + i; // print file ID if it has not moved
+ }
+ }
+ for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) {
+ piece = boards[move][BOARD_HEIGHT-1][i];
+ if(piece >= BlackPawn && piece <= BlackKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move
+ if(!(boards[move][TOUCHED_B] & 1<<i)) *p++ = 'a' + i; // print file ID if it has not moved
+ }
+ }
+ if(p == q) *p++ = '-';
+ *p++ = ' ';
+ }
+
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;
} else {
- if(nrCastlingRights) {
+ if(haveRights) {
int handW=0, handB=0;
if(gameInfo.variant == VariantSChess) { // for S-Chess, all virgin backrank pieces must be listed
for(i=0; i<BOARD_HEIGHT; i++) handW += boards[move][i][BOARD_RGHT]; // count white held pieces
while (emptycount--)
board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
if (*p == '/') p++;
- else if(autoSize) { // we stumbled unexpectedly into end of board
+ else if(autoSize && i != BOARD_HEIGHT-1) { // we stumbled unexpectedly into end of board
for(k=i; k<BOARD_HEIGHT; k++) { // too few ranks; shift towards bottom
for(j=0; j<BOARD_WIDTH; j++) board[k-i][j] = board[k][j];
}
}
while (*p == '/' || *p == ' ') p++;
- if(autoSize) appData.NrFiles = w, InitPosition(TRUE);
+ if(autoSize && w != 0) appData.NrFiles = w, InitPosition(TRUE);
/* [HGM] by default clear Crazyhouse holdings, if present */
if(gameInfo.holdingsWidth) {
&& board[castlingRank[5]][initialRights[5]] != BlackKing) board[CASTLING][5] = NoRights;
FENrulePlies = 0;
+ if(pieceDesc[WhiteKing] && strchr(pieceDesc[WhiteKing], 'i') && !strchr(pieceDesc[WhiteKing], 'O')) { // redefined without castling
+ char *q = p;
+ int w=0, b=0;
+ while(isalpha(*p)) {
+ if(isupper(*p)) w |= 1 << (*p++ - 'A');
+ if(islower(*p)) b |= 1 << (*p++ - 'a');
+ }
+ if(*p == '-') p++;
+ if(p != q) {
+ board[TOUCHED_W] = ~w;
+ board[TOUCHED_B] = ~b;
+ while(*p == ' ') p++;
+ }
+ } else
+
if(nrCastlingRights) {
int fischer = 0;
if(gameInfo.variant == VariantSChess) for(i=0; i<BOARD_FILES; i++) virgin[i] = 0;