X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=backend.c;h=a89311b37202ff6dea19236d77df08aa570802a3;hp=b2cd7c3c42c998220e3cb2db062a1b9565dc5293;hb=5cab485d7a39f1b15558fc3b06d57d2164a7dc5d;hpb=e4def842c0f4ed63df0196ac34ffdeb6a12304fe diff --git a/backend.c b/backend.c index b2cd7c3..a89311b 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 */ @@ -387,7 +387,7 @@ u64ToDouble (u64 value) by this function. */ int -PosFlags (index) +PosFlags (int index) { int flags = F_ALL_CASTLE_OK; if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE; @@ -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(); } @@ -1743,6 +1744,11 @@ InitBackEnd3 P((void)) CopyBoard(filePosition, boards[0]); CopyBoard(initialPosition, boards[0]); } + } else if(*appData.fen != NULLCHAR) { + if(ParseFEN(filePosition, &blackPlaysFirst, appData.fen, TRUE) && !blackPlaysFirst) { + startedFromPositionFile = TRUE; + Reset(TRUE, TRUE); + } } if (initialMode == AnalyzeMode) { if (appData.noChessProgram) { @@ -6454,6 +6460,7 @@ InitPosition (int redraw) initialRights[i] = filePosition[CASTLING][i]; startedFromSetupPosition = TRUE; } + if(*appData.men) LoadPieceDesc(appData.men); CopyBoard(boards[0], initialPosition); @@ -6975,6 +6982,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) @@ -7102,9 +7110,15 @@ 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]--; @@ -7161,6 +7175,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; } @@ -7431,7 +7446,7 @@ MarkTargetSquares (int clear) if(clear) { // no reason to ever suppress clearing for(x=0; x= 0) { @@ -7678,7 +7695,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) doubleClick = first.excludeMoves; // used by UserMoveEvent to recognize exclude moves } promoDefaultAltered = FALSE; - MarkTargetSquares(1); + if(!second) MarkTargetSquares(1); if(!(second && appData.oneClick && OnlyMove(&x, &y, TRUE))) { if (appData.highlightDragging) { SetHighlights(x, y, -1, -1); @@ -7735,10 +7752,11 @@ LeftClick (ClickType clickType, int xPix, int yPix) second = 0; fromX = fromY = -1; gatingPiece = EmptySquare; - MarkTargetSquares(1); ClearHighlights(); gotPremove = 0; ClearPremoveHighlights(); + MarkTargetSquares(-1); + DrawPosition(FALSE, NULL); // make user highlights are drawn (and deferred marker clearing) } else { /* First upclick in same square; start click-click mode */ SetHighlights(x, y, -1, -1); @@ -7787,6 +7805,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED(piece)) == '+') promoSweep = CHUPROMOTED(piece); selectFlag = 0; lastX = xPix; lastY = yPix; ReportClick("put", x, y); // extra put to prompt engine for 'choice' command + saveFlash = appData.flashCount; appData.flashCount = 0; Sweep(0); // Pawn that is going to promote: preview promotion piece sweepSelecting = 1; DisplayMessage("", _("Pull pawn backwards to under-promote")); @@ -7800,14 +7819,16 @@ LeftClick (ClickType clickType, int xPix, int yPix) } else { ClearHighlights(); } + MarkTargetSquares(1); } else if(sweepSelecting) { // this must be the up-click corresponding to the down-click that started the sweep sweepSelecting = 0; appData.animate = FALSE; // do not animate, a selected piece already on to-square - *promoRestrict = 0; + *promoRestrict = 0; appData.flashCount = saveFlash; if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); } else { ClearHighlights(); } + MarkTargetSquares(1); } else { #if 0 // [HGM] this must be done after the move is made, as with arrow it could lead to a board redraw with piece still on from square @@ -7837,6 +7858,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) DragPieceEnd(xPix, yPix); dragging = 0; /* Don't animate move and drag both */ appData.animate = FALSE; + MarkTargetSquares(-1); // -1 defers displaying marker change to prevent piece reappearing on from-square! } // moves into holding are invalid for now (except in EditPosition, adapting to-square) @@ -7894,19 +7916,20 @@ LeftClick (ClickType clickType, int xPix, int yPix) 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]); - MarkTargetSquares(1); fromX = fromY = -1; + flashing = 0; } appData.animate = saveAnimate; if (appData.animate || appData.animateDragging) { /* Undo animation damage if needed */ - DrawPosition(FALSE, NULL); +// DrawPosition(FALSE, NULL); } } @@ -8042,6 +8065,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 ); } @@ -8934,11 +8960,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); @@ -9677,6 +9703,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) { @@ -9705,10 +9732,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)) { @@ -10775,6 +10825,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, ','); @@ -11410,6 +11461,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(); } @@ -11817,6 +11873,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, @@ -11957,7 +12023,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; @@ -12089,21 +12158,17 @@ AutoPlayOneMove () SetHighlights(-1, -1, toX, toY); } } else { - int viaX = moveList[currentMove][5] - AAA; - int viaY = moveList[currentMove][6] - ONE; fromX = moveList[currentMove][0] - AAA; fromY = moveList[currentMove][1] - ONE; HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove); /* [AS] */ if(moveList[currentMove][4] == ';') { // multi-leg - ChessSquare piece = boards[currentMove][viaY][viaX]; - AnimateMove(boards[currentMove], fromX, fromY, viaX, viaY); - boards[currentMove][viaY][viaX] = boards[currentMove][fromY][fromX]; - AnimateMove(boards[currentMove], fromX=viaX, fromY=viaY, toX, toY); - boards[currentMove][viaY][viaX] = piece; - } else + killX = moveList[currentMove][5] - AAA; + killY = moveList[currentMove][6] - ONE; + } AnimateMove(boards[currentMove], fromX, fromY, toX, toY); + killX = killY = -1; if (appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); @@ -12924,7 +12989,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList) char buf[MSG_SIZ]; int gn = gameNumber; ListGame *lg = NULL; - int numPGNTags = 0; + int numPGNTags = 0, i; int err, pos = -1; GameMode oldGameMode; VariantClass v, oldVariant = gameInfo.variant; /* [HGM] PGNvariant */ @@ -13113,6 +13178,8 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList) if (appData.debugMode) fprintf(debugFP, "Parsed game start '%s' (%d)\n", yy_text, (int) cm); + for(i=0; i10000 || appData.matchPause<10) appData.matchPause = 10000; /* [HGM] make pause adjustable */ @@ -14991,6 +15063,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) { @@ -15000,6 +15073,7 @@ TwoMachinesEvent P((void)) for (i = backwardMostMove; i < forwardMostMove; i++) { SendMoveToProgram(i, &second); } + } gameMode = TwoMachinesPlay; pausing = startingEngine = FALSE; @@ -15018,11 +15092,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) { @@ -15217,10 +15293,10 @@ EditGameEvent () SetGameInfo(); } - void EditPositionEvent () { + int i; if (gameMode == EditPosition) { EditGameEvent(); return; @@ -15232,8 +15308,11 @@ EditPositionEvent () gameMode = EditPosition; ModeHighlight(); SetGameInfo(); + CopyBoard(rightsBoard, nullBoard); if (currentMove > 0) CopyBoard(boards[0], boards[currentMove]); + for(i=0; i>1 || appData.fischerCastling)) hasRights = 1; default: defaultlabel: if (gameMode == IcsExamining) { @@ -15511,6 +15599,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) { @@ -15860,19 +15949,15 @@ ForwardInner (int target) SetHighlights(-1, -1, toX, toY); } } else { - int viaX = moveList[target - 1][5] - AAA; - int viaY = moveList[target - 1][6] - ONE; fromX = moveList[target - 1][0] - AAA; fromY = moveList[target - 1][1] - ONE; if (target == currentMove + 1) { if(moveList[target - 1][4] == ';') { // multi-leg - ChessSquare piece = boards[currentMove][viaY][viaX]; - AnimateMove(boards[currentMove], fromX, fromY, viaX, viaY); - boards[currentMove][viaY][viaX] = boards[currentMove][fromY][fromX]; - AnimateMove(boards[currentMove], viaX, viaY, toX, toY); - boards[currentMove][viaY][viaX] = piece; - } else + killX = moveList[target - 1][5] - AAA; + killY = moveList[target - 1][6] - ONE; + } AnimateMove(boards[currentMove], fromX, fromY, toX, toY); + killX = killY = -1; } if (appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY);