if(!blackPlaysFirst) {
startedFromPositionFile = TRUE;
CopyBoard(filePosition, boards[0]);
+ CopyBoard(initialPosition, boards[0]);
}
}
if (initialMode == AnalyzeMode) {
} 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;
for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
for( i=offs=0; i<NrPieces/2-1; i++ ) {
char *p;
- if(map[j] == '/' && *escapes) offs = CHUPROMOTED WhitePawn - i, j++;
+ if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
table[i + offs] = map[j++];
if(p = strchr(escapes, map[j])) j++, table[i + offs] += 64*(p - escapes + 1);
}
table[(int) WhiteKing] = map[j++];
for( i=offs=0; i<NrPieces/2-1; i++ ) {
char *p;
- if(map[j] == '/' && *escapes) offs = CHUPROMOTED WhitePawn - i, j++;
+ if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
table[WHITE_TO_BLACK i + offs] = map[j++];
if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i + offs] += 64*(p - escapes + 1);
}
if ((int) *bp < (int) BlackPawn) {
if(j == BOARD_RGHT+1)
snprintf(message, MSG_SIZ, "%c@%d\n", PieceToChar(*bp), bp[-1]);
- else snprintf(message, MSG_SIZ, "%c%c%c\n", PieceToChar(*bp), AAA + j, ONE + i);
+ else snprintf(message, MSG_SIZ, "%c%c%d\n", PieceToChar(*bp), AAA + j, ONE + i - '0');
if(message[0] == '+' || message[0] == '~') {
- snprintf(message, MSG_SIZ,"%c%c%c+\n",
+ snprintf(message, MSG_SIZ,"%c%c%d+\n",
PieceToChar((ChessSquare)(DEMOTED *bp)),
- AAA + j, ONE + i);
+ AAA + j, ONE + i - '0');
}
if(cps->alphaRank) { /* [HGM] shogi: translate coords */
message[1] = BOARD_RGHT - 1 - j + '1';
&& ((int) *bp >= (int) BlackPawn)) {
if(j == BOARD_LEFT-2)
snprintf(message, MSG_SIZ, "%c@%d\n", ToUpper(PieceToChar(*bp)), bp[1]);
- else snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
- AAA + j, ONE + i);
+ else snprintf(message,MSG_SIZ, "%c%c%d\n", ToUpper(PieceToChar(*bp)),
+ AAA + j, ONE + i - '0');
if(message[0] == '+' || message[0] == '~') {
- snprintf(message, MSG_SIZ,"%c%c%c+\n",
+ snprintf(message, MSG_SIZ,"%c%c%d+\n",
PieceToChar((ChessSquare)(DEMOTED *bp)),
- AAA + j, ONE + i);
+ AAA + j, ONE + i - '0');
}
if(cps->alphaRank) { /* [HGM] shogi: translate coords */
message[1] = BOARD_RGHT - 1 - j + '1';
return;
}
}
-printf("to click %d,%d\n",x,y);
+
/* fromX != -1 */
if (clickType == Press && gameMode != EditPosition) {
ChessSquare fromP;
// ignore clicks on holdings
if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
}
-printf("A type=%d\n",clickType);
- if(x == fromX && y == fromY && gameMode == EditPosition && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) {
+ if(x == fromX && y == fromY && clickType == Press && gameMode == EditPosition && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) {
gatingPiece = boards[currentMove][fromY][fromX]; // prepare to copy rather than move
+ DragPieceBegin(xPix, yPix, FALSE); dragging = 1;
return;
}
}
clearFlag = 0;
-printf("B\n");
+
if(gameMode != EditPosition && !appData.testLegality && !legal[y][x] &&
fromX >= BOARD_LEFT && fromX < BOARD_RGHT && (x != killX || y != killY) && !sweepSelecting) {
if(dragging) DragPieceEnd(xPix, yPix), dragging = 0;
DrawPosition(TRUE, NULL);
return; // ignore to-click
}
-printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y);
+
/* we now have a different from- and (possibly off-board) to-square */
/* Completed move */
if(!sweepSelecting) {
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)) {
}
/* End of code added by Tord */
+ } else if (pieceDesc[piece] && piece == king && !strchr(pieceDesc[piece], 'O') && strchr(pieceDesc[piece], 'i')) {
+ board[fromY][fromX] = EmptySquare; // never castle if King has virgin moves defined on it other than castling
+ board[toY][toX] = piece;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
case BlackASideCastleFR:
/* POP Fabien */
if (appData.debugMode)
- fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString);
+ fprintf(debugFP, "Parsed %s into %s virgin=%x,%x\n", yy_text, currentMoveString, boards[forwardMostMove][TOUCHED_W], boards[forwardMostMove][TOUCHED_B]);
fromX = currentMoveString[0] - AAA;
fromY = currentMoveString[1] - ONE;
toX = currentMoveString[2] - AAA;
gameInfo.event = StrSave(yy_text);
}
- startedFromSetupPosition = FALSE;
+ startedFromSetupPosition = startedFromPositionFile; // [HGM]
while (cm == PGNTag) {
if (appData.debugMode)
fprintf(debugFP, "Parsed PGNTag: %s\n", yy_text);
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
/* [HGM] write true castling rights */
if( nrCastlingRights == 6 ) {
int q, k=0;
- if(boards[move][CASTLING][0] == BOARD_RGHT-1 &&
+ if(boards[move][CASTLING][0] != NoRights &&
boards[move][CASTLING][2] != NoRights ) k = 1, *p++ = 'K';
- q = (boards[move][CASTLING][1] == BOARD_LEFT &&
+ q = (boards[move][CASTLING][1] != NoRights &&
boards[move][CASTLING][2] != NoRights );
if(handW) { // for S-Chess with pieces in hand, list virgin pieces between K and Q
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
}
if(q) *p++ = 'Q';
k = 0;
- if(boards[move][CASTLING][3] == BOARD_RGHT-1 &&
+ if(boards[move][CASTLING][3] != NoRights &&
boards[move][CASTLING][5] != NoRights ) k = 1, *p++ = 'k';
- q = (boards[move][CASTLING][4] == BOARD_LEFT &&
+ q = (boards[move][CASTLING][4] != NoRights &&
boards[move][CASTLING][5] != NoRights );
if(handB) {
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
int i, j, k, w=0, subst=0, shuffle=0, wKingRank = -1, bKingRank = -1;
char *p, c;
int emptycount, virgin[BOARD_FILES];
- ChessSquare piece;
+ ChessSquare piece, king = (gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing);
p = fen;
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];
}
p++;
}
board[i][(j++)+gameInfo.holdingsWidth] = piece;
- if(piece == WhiteKing) wKingRank = i;
- if(piece == BlackKing) bKingRank = i;
+ if(piece == king) wKingRank = i;
+ if(piece == WHITE_TO_BLACK king) bKingRank = i;
} else {
return FALSE;
}
}
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) {
/* set defaults in case FEN is incomplete */
board[EP_STATUS] = EP_UNKNOWN;
+ board[TOUCHED_W] = board[TOUCHED_B] = 0;
for(i=0; i<nrCastlingRights; i++ ) {
board[CASTLING][i] =
appData.fischerCastling ? NoRights : initialRights[i];
&& 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;
}
if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate)
whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // for these variant scanning fails
- if(whiteKingFile == NoRights || board[0][whiteKingFile] != WhiteUnicorn
- && board[0][whiteKingFile] != WhiteKing) whiteKingFile = NoRights;
- if(blackKingFile == NoRights || board[BOARD_HEIGHT-1][blackKingFile] != BlackUnicorn
- && board[BOARD_HEIGHT-1][blackKingFile] != BlackKing) blackKingFile = NoRights;
+ if(whiteKingFile == NoRights || board[castlingRank[2]][whiteKingFile] != WhiteUnicorn
+ && board[castlingRank[2]][whiteKingFile] != WhiteKing) whiteKingFile = NoRights;
+ if(blackKingFile == NoRights || board[castlingRank[5]][blackKingFile] != BlackUnicorn
+ && board[castlingRank[5]][blackKingFile] != BlackKing) blackKingFile = NoRights;
switch(c) {
case'K':
for(i=BOARD_RGHT-1; board[castlingRank[2]][i]!=WhiteRook && i>whiteKingFile; i--);