X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=backend.c;h=83034f4de42b57cdf7331f76ee399aa8cf664d20;hp=734cf407d07818ac4327a4bb8c3fafe55de6f001;hb=88785b48e8eff991f222cd7fa96a2b5ac6345fad;hpb=2087ac0f61e84f7f71cbea5a0a3325374f9e76ee diff --git a/backend.c b/backend.c index 734cf40..83034f4 100644 --- a/backend.c +++ b/backend.c @@ -296,7 +296,7 @@ int promoDefaultAltered; 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 */ @@ -564,8 +564,8 @@ ChessSquare KnightmateArray[2][BOARD_FILES] = { ChessSquare SpartanArray[2][BOARD_FILES] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, - { BlackAlfil, BlackMarshall, BlackKing, BlackDragon, - BlackDragon, BlackKing, BlackAngel, BlackAlfil } + { BlackAlfil, BlackDragon, BlackKing, BlackTower, + BlackTower, BlackKing, BlackAngel, BlackAlfil } }; ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */ @@ -691,18 +691,18 @@ ChessSquare CourierArray[2][BOARD_FILES] = { BlackFerz, BlackWazir, BlackBishop, BlackAlfil, BlackKnight, BlackRook } }; ChessSquare ChuArray[6][BOARD_FILES] = { - { WhiteLance, WhiteUnicorn, WhiteMan, WhiteFerz, WhiteWazir, WhiteKing, - WhiteAlfil, WhiteWazir, WhiteFerz, WhiteMan, WhiteUnicorn, WhiteLance }, - { BlackLance, BlackUnicorn, BlackMan, BlackFerz, BlackWazir, BlackAlfil, - BlackKing, BlackWazir, BlackFerz, BlackMan, BlackUnicorn, BlackLance }, - { WhiteCannon, EmptySquare, WhiteBishop, EmptySquare, WhiteNightrider, WhiteMarshall, - WhiteAngel, WhiteNightrider, EmptySquare, WhiteBishop, EmptySquare, WhiteCannon }, - { BlackCannon, EmptySquare, BlackBishop, EmptySquare, BlackNightrider, BlackAngel, - BlackMarshall, BlackNightrider, EmptySquare, BlackBishop, EmptySquare, BlackCannon }, - { WhiteFalcon, WhiteSilver, WhiteRook, WhiteCardinal, WhiteDragon, WhiteLion, - WhiteQueen, WhiteDragon, WhiteCardinal, WhiteRook, WhiteSilver, WhiteFalcon }, - { BlackFalcon, BlackSilver, BlackRook, BlackCardinal, BlackDragon, BlackQueen, - BlackLion, BlackDragon, BlackCardinal, BlackRook, BlackSilver, BlackFalcon } + { WhiteLance, WhiteCat, WhiteCopper, WhiteFerz, WhiteWazir, WhiteKing, + WhiteAlfil, WhiteWazir, WhiteFerz, WhiteCopper, WhiteCat, WhiteLance }, + { BlackLance, BlackCat, BlackCopper, BlackFerz, BlackWazir, BlackAlfil, + BlackKing, BlackWazir, BlackFerz, BlackCopper, BlackCat, BlackLance }, + { WhiteAxe, EmptySquare, WhiteBishop, EmptySquare, WhiteClaw, WhiteMarshall, + WhiteAngel, WhiteClaw, EmptySquare, WhiteBishop, EmptySquare, WhiteAxe }, + { BlackAxe, EmptySquare, BlackBishop, EmptySquare, BlackClaw, BlackAngel, + BlackMarshall, BlackClaw, EmptySquare, BlackBishop, EmptySquare, BlackAxe }, + { WhiteDagger, WhiteSword, WhiteRook, WhiteCardinal, WhiteDragon, WhiteLion, + WhiteQueen, WhiteDragon, WhiteCardinal, WhiteRook, WhiteSword, WhiteDagger }, + { BlackDagger, BlackSword, BlackRook, BlackCardinal, BlackDragon, BlackQueen, + BlackLion, BlackDragon, BlackCardinal, BlackRook, BlackSword, BlackDagger } }; #else // !(BOARD_FILES>=12) #define CourierArray CapablancaArray @@ -996,6 +996,7 @@ Load (ChessProgramState *cps, int i) SwapEngines(i); ReplaceEngine(cps, i); FloatToFront(&appData.recentEngineList, engineLine); + if(gameMode == BeginningOfGame) Reset(TRUE, TRUE); return; } p = engineName; @@ -1585,7 +1586,7 @@ MatchEvent (int mode) } 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(); } @@ -3394,7 +3395,8 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int #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 ( @@ -6278,8 +6280,10 @@ InitPosition (int redraw) gameInfo.boardWidth = 12; gameInfo.boardHeight = 12; nrCastlingRights = 0; - SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN.........^T..^L......^A^H/^F^G^M.^E^X^O^I.^P.^B^R..^D^S^C^VK" - "p.brqsexogcathd.vmlifn.........^t..^l......^a^h/^f^g^m.^e^x^o^i.^p.^b^r..^d^s^c^vk", SUFFIXES); +// SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN.........^T..^L......^A^H/^F^G^M.^E^X^O^I.^P.^B^R..^D^S^C^VK" + // "p.brqsexogcathd.vmlifn.........^t..^l......^a^h/^f^g^m.^e^x^o^i.^p.^b^r..^d^s^c^vk", SUFFIXES); + SetCharTableEsc(pieceToChar, "P.BRQSEXOG...HD..^DLI^HNV........^T..^L.C...A^AFT/^F^G^M.^E^X^O^I.^P.^B^R..M^S^C^VK" + "p.brqsexog...hd..^dli^hnv........^t..^l.c...a^aft/^f^g^m.^e^x^o^i.^p.^b^r..m^s^c^vk", SUFFIXES); break; case VariantCourier: pieces = CourierArray; @@ -6293,7 +6297,7 @@ InitPosition (int redraw) break; case VariantSpartan: pieces = SpartanArray; - SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k"); + SetCharTable(pieceToChar, "PNBRQ.....................K......lw......g...h......ck"); break; case VariantLion: pieces = lionArray; @@ -6981,6 +6985,7 @@ char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ]; ChessMove lastLoadGameStart = EndOfFile; int doubleClick; Boolean addToBookFlag; +static Board rightsBoard, nullBoard; void UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar) @@ -7108,8 +7113,13 @@ 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 || p == WhitePawn || p == BlackPawn) { + int n = rightsBoard[toY][toX] ^= 1; // toggle virginity of K or R + DisplayMessage("", n ? _("rights granted") : _("rights revoked")); + gatingPiece = p; + } + } else rightsBoard[toY][toX] = 0; // revoke rights on moving boards[0][toY][toX] = boards[0][fromY][fromX]; if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings if(boards[0][fromY][0] != EmptySquare) { @@ -7167,6 +7177,7 @@ UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar) 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; } @@ -7904,13 +7915,14 @@ LeftClick (ClickType clickType, int xPix, int yPix) DisplayMessage("Click in holdings to choose piece", ""); return; } + DrawPosition(FALSE, NULL); // shows piece on from-square during promo popup PromotionPopUp(promoChoice); } else { int oldMove = currentMove; 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]); @@ -8056,6 +8068,9 @@ SendProgramStatsToFrontend (ChessProgramState * cps, ChessProgramStats * cpstats if(stats.pv && stats.pv[0]) safeStrCpy(lastPV[stats.which], stats.pv, sizeof(lastPV[stats.which])/sizeof(lastPV[stats.which][0])); // [HGM] pv: remember last PV of each + if( gameMode == AnalyzeMode && stats.pv && stats.pv[0] + && appData.analysisBell && stats.time >= 100*appData.analysisBell ) RingBell(); + SetProgramStats( &stats ); } @@ -8948,11 +8963,11 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } if(appData.epd) { if(solvingTime >= 0) { - snprintf(buf1, MSG_SIZ, "%d. %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); @@ -9131,10 +9146,10 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } if(sscanf(message, "piece %s %s", buf2, buf1) == 2) { ChessSquare piece = WhitePawn; - char *p=message+6, *q, *s = SUFFIXES, ID = *p; - if(*p == '+') piece = CHUPROMOTED(WhitePawn), ID = *++p; + char *p=message+6, *q, *s = SUFFIXES, ID = *p, promoted = 0; + if(*p == '+') promoted++, ID = *++p; if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++; - piece += CharToPiece(ID & 255) - WhitePawn; + piece = CharToPiece(ID & 255); if(promoted) piece = CHUPROMOTED(piece); if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR /* always accept definition of */ && piece != WhiteFalcon && piece != BlackFalcon /* wild-card pieces. */ && piece != WhiteCobra && piece != BlackCobra @@ -9266,7 +9281,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h 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; @@ -9691,6 +9706,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h 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) { @@ -9719,10 +9735,33 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h 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)) { @@ -10288,7 +10327,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } 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; @@ -10296,7 +10336,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } 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; @@ -10339,7 +10380,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } 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; @@ -10347,7 +10389,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } 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; @@ -10789,6 +10832,7 @@ InitChessProgram (ChessProgramState *cps, int setup) b = SupportedVariant(cps->variants, gameInfo.variant, gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->protocolVersion, cps->tidy); + if (b == NULL) { VariantClass v; char c, *q = cps->variants, *p = strchr(q, ','); @@ -11041,8 +11085,10 @@ Substitute (char *participants, int expunge) 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); } @@ -11424,6 +11470,11 @@ NextMatchGame () res = LoadGameOrPosition(matchGame); // setup game appData.noChessProgram = FALSE; // LoadGameOrPosition might call Reset too! if(!res) return; // abort when bad game/pos file + if(appData.epd) {// in EPD mode we make sure first engine is to move + firstWhite = !(forwardMostMove & 1); + first.twoMachinesColor = firstWhite ? "white\n" : "black\n"; // perform actual color assignement + second.twoMachinesColor = firstWhite ? "black\n" : "white\n"; + } TwoMachinesEvent(); } @@ -11831,6 +11882,16 @@ GameEnds (ChessMove result, char *resultDetails, int whosays) 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, @@ -11971,7 +12032,10 @@ Reset (int redraw, int init) lastHint[0] = NULLCHAR; ClearGameInfo(&gameInfo); gameInfo.variant = StringToVariant(appData.variant); - if(gameInfo.variant == VariantNormal && strcmp(appData.variant, "normal")) gameInfo.variant = VariantUnknown; + if(gameInfo.variant == VariantNormal && strcmp(appData.variant, "normal")) { + gameInfo.variant = VariantUnknown; + strncpy(engineVariant, appData.variant, MSG_SIZ); + } ics_user_moved = ics_clock_paused = FALSE; ics_getting_history = H_FALSE; ics_gamenum = -1; @@ -13518,9 +13582,12 @@ LoadPosition (FILE *f, int positionNumber, char *title) DisplayError(_("Bad FEN position in file"), 0); return FALSE; } - if((p = strstr(line, ";")) && (p = strstr(p+1, "bm "))) { // EPD with best move - sscanf(p+3, "%s", bestMove); + if((strchr(line, ';')) && (p = strstr(line, " bm "))) { // EPD with best move + 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); @@ -13859,6 +13926,10 @@ SaveGamePGN2 (FILE *f) snprintf(buf, MSG_SIZ, " %d:%02d%c", seconds/60, seconds%60, 0); } + if(appData.cumulativeTimePGN) { + snprintf(buf, MSG_SIZ, " %+ld", timeRemaining[i & 1][i+1]/1000); + } + snprintf( move_buffer, sizeof(move_buffer)/sizeof(move_buffer[0]),"{%s%.2f/%d%s}", pvInfoList[i].score >= 0 ? "+" : "", pvInfoList[i].score / 100.0, @@ -14974,6 +15045,7 @@ TwoMachinesEvent P((void)) 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, @@ -14992,6 +15064,7 @@ TwoMachinesEvent P((void)) 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 */ @@ -15003,6 +15076,7 @@ TwoMachinesEvent P((void)) // we are now committed to starting the game stalling = 0; DisplayMessage("", ""); + if(!appData.epd) { if (startedFromSetupPosition) { SendBoard(&second, backwardMostMove); if (appData.debugMode) { @@ -15012,6 +15086,7 @@ TwoMachinesEvent P((void)) for (i = backwardMostMove; i < forwardMostMove; i++) { SendMoveToProgram(i, &second); } + } gameMode = TwoMachinesPlay; pausing = startingEngine = FALSE; @@ -15030,11 +15105,13 @@ TwoMachinesEvent P((void)) 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) { @@ -15229,10 +15306,10 @@ EditGameEvent () SetGameInfo(); } - void EditPositionEvent () { + int i; if (gameMode == EditPosition) { EditGameEvent(); return; @@ -15244,8 +15321,11 @@ EditPositionEvent () gameMode = EditPosition; ModeHighlight(); SetGameInfo(); + CopyBoard(rightsBoard, nullBoard); if (currentMove > 0) CopyBoard(boards[0], boards[currentMove]); + for(i=0; i>1; - if(boards[0][0][BOARD_WIDTH>>1] == king) { - boards[0][CASTLING][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? BOARD_LEFT : NoRights; - boards[0][CASTLING][0] = boards[0][0][BOARD_RGHT-1] == WhiteRook ? BOARD_RGHT-1 : NoRights; - } else boards[0][CASTLING][2] = NoRights; - if(boards[0][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == WHITE_TO_BLACK king) { - boards[0][CASTLING][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? BOARD_LEFT : NoRights; - boards[0][CASTLING][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : NoRights; - } else boards[0][CASTLING][5] = NoRights; - if(gameInfo.variant == VariantSChess) { - int i; - for(i=BOARD_LEFT; i=0; r--) for(f=BOARD_RGHT-1; f>=BOARD_LEFT; f--) { // first pass: Kings & e.p. + if(rightsBoard[r][f]) { + ChessSquare p = boards[0][r][f]; + if(p == (blackPlaysFirst ? WhitePawn : BlackPawn)) boards[0][EP_STATUS] = f; + else if(p == king) boards[0][CASTLING][2] = f; + else if(p == WHITE_TO_BLACK king) boards[0][CASTLING][5] = f; + else rightsBoard[r][f] = 2; // mark for second pass + } + } + for(r=BOARD_HEIGHT-1; r>=0; r--) for(f=BOARD_RGHT-1; f>=BOARD_LEFT; f--) { // second pass: Rooks + if(rightsBoard[r][f] == 2) { + ChessSquare p = boards[0][r][f]; + if(p == WhiteRook) boards[0][CASTLING][(f < boards[0][CASTLING][2])] = f; else + if(p == BlackRook) boards[0][CASTLING][(f < boards[0][CASTLING][5])+3] = f; } } } @@ -15393,6 +15474,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) 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; @@ -15425,14 +15507,16 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) } } } + CopyBoard(rightsBoard, nullBoard); if(gameMode != IcsExamining) { // [HGM] editpos: cycle trough boards - int r; + int r, i; for(r = 0; r < BOARD_HEIGHT; r++) { for(x = BOARD_LEFT; x < BOARD_RGHT; x++) { // create 'menu board' by removing duplicates ChessSquare p = menuBoard[r][x]; for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[r][y] == p) menuBoard[r][y] = EmptySquare; } } + menuBoard[CASTLING][0] = menuBoard[CASTLING][3] = NoRights; // h-side Rook was deleted DisplayMessage("Clicking clock again restores position", ""); if(gameInfo.variant != lastVariant) lastVariant = gameInfo.variant, CopyBoard(erasedBoard, boards[0]); if(!nonEmpty) { // asked to clear an empty board @@ -15447,6 +15531,8 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) } else CopyBoard(erasedBoard, currentBoard); + for(i=0; i>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) { @@ -15523,6 +15618,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) 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) { @@ -16722,7 +16818,11 @@ GetInfoFromComment (int index, char * text) 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; } @@ -18166,7 +18266,9 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) } 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;