X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=65f517708e8fd689fc1e21e48a862d98852af706;hb=43aacbdf1c19177fe05487e0c76e207189e5bdb0;hp=c4e931643a1c3f0345c913401a4c9f6e5aa48fd6;hpb=941395daf4333598be57255c9b722c7c09b3adf3;p=xboard.git diff --git a/backend.c b/backend.c index c4e9316..65f5177 100755 --- a/backend.c +++ b/backend.c @@ -450,6 +450,20 @@ int loadFlag = 0; int shuffleOpenings; int mute; // mute all sounds +// [HGM] vari: next 12 to save and restore variations +#define MAX_VARIATIONS 10 +int framePtr = MAX_MOVES-1; // points to free stack entry +int storedGames = 0; +int savedFirst[MAX_VARIATIONS]; +int savedLast[MAX_VARIATIONS]; +int savedFramePtr[MAX_VARIATIONS]; +char *savedDetails[MAX_VARIATIONS]; +ChessMove savedResult[MAX_VARIATIONS]; + +void PushTail P((int firstMove, int lastMove)); +Boolean PopTail P((void)); +void CleanupTail P((void)); + ChessSquare FIDEArray[2][BOARD_FILES] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, @@ -641,7 +655,7 @@ InitBackEnd1() { int i, j; - for( i=0; i= MAX_MOVES) { + if (moveNum > framePtr) { // [HGM] vari: do not run into saved variations DisplayFatalError(_("Game too long; increase MAX_MOVES and recompile"), 0, 1); return; @@ -4611,7 +4625,7 @@ InitPosition(redraw) /* [AS] Initialize pv info list [HGM] and game status */ { - for( i=0; i in stead of calling FinishMove directly, this function is made into one that returns an OK move type if FinishMove @@ -5324,7 +5333,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar) /*char*/int promoChar; { char *bookHit = 0; -if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar); + if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { // [HGM] superchess: suppress promotions to non-available piece int k = PieceToNumber(CharToPiece(ToUpper(promoChar))); @@ -5339,13 +5348,12 @@ if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", move move type in caller when we know the move is a legal promotion */ if(moveType == NormalMove && promoChar) moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar); -if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar); + /* [HGM] convert drag-and-drop piece drops to standard form */ if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop; if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]); -// fromX = boards[currentMove][fromY][fromX]; // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings @@ -5354,7 +5362,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move } /* [HGM] The following if has been moved here from - UserMoveEvent(). Because it seemed to belon here (why not allow + UserMoveEvent(). Because it seemed to belong here (why not allow piece drops in training games?), and because it can only be performed after it is known to what we promote. */ if (gameMode == Training) { @@ -5394,8 +5402,9 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move /* Ok, now we know that the move is good, so we can kill the previous line in Analysis Mode */ - if (gameMode == AnalyzeMode && currentMove < forwardMostMove) { - forwardMostMove = currentMove; + if ((gameMode == AnalyzeMode || gameMode == EditGame) + && currentMove < forwardMostMove) { + PushTail(currentMove, forwardMostMove); // [HGM] vari: save tail of game } /* If we need the chess program but it's dead, restart it */ @@ -5428,7 +5437,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move } ModeHighlight(); } -if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar); + /* Relay move to ICS or chess engine */ if (appData.icsActive) { if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || @@ -7686,7 +7695,7 @@ MakeMove(fromX, fromY, toX, toY, promoChar) fflush(serverMoves); } - if (forwardMostMove+1 >= MAX_MOVES) { + if (forwardMostMove+1 > framePtr) { // [HGM] vari: do not run into saved variations DisplayFatalError(_("Game too long; increase MAX_MOVES and recompile"), 0, 1); return; @@ -8468,6 +8477,7 @@ Reset(redraw, init) fprintf(debugFP, "Reset(%d, %d) from gameMode %d\n", redraw, init, gameMode); } + CleanupTail(); // [HGM] vari: delete any stored variations pausing = pauseExamInvalid = FALSE; startedFromSetupPosition = blackPlaysFirst = FALSE; firstMove = TRUE; @@ -10861,7 +10871,8 @@ TwoMachinesEvent P((void)) break; } - forwardMostMove = currentMove; +// forwardMostMove = currentMove; + TruncateGame(); // [HGM] vari: MachineWhite and MachineBlack do this... ResurrectChessProgram(); /* in case first program isn't running */ if (second.pr == NULL) { @@ -11785,7 +11796,7 @@ void ToStartEvent() { if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { - /* to optimze, we temporarily turn off analysis mode while we undo + /* to optimize, we temporarily turn off analysis mode while we undo * all the moves. Otherwise we get analysis output after each undo. */ if (first.analysisSupport) { @@ -11826,6 +11837,9 @@ ToNrEvent(int to) void RevertEvent() { + if(PopTail()) { // [HGM] vari: restore old game tail + return; + } if (gameMode != IcsExamining) { DisplayError(_("You are not examining a game"), 0); return; @@ -11923,6 +11937,7 @@ TruncateGameEvent() void TruncateGame() { + CleanupTail(); // [HGM] vari: only keep current variation if we explicitly truncate if (forwardMostMove > currentMove) { if (gameInfo.resultDetails != NULL) { free(gameInfo.resultDetails); @@ -14117,3 +14132,95 @@ int wrap(char *dest, char *src, int count, int width, int *lp) return len; } + +// [HGM] vari: routines for shelving variations + +void +PushTail(int firstMove, int lastMove) +{ + int i, j, nrMoves = lastMove - firstMove; + + if(appData.icsActive) { // only in local mode + forwardMostMove = currentMove; // mimic old ICS behavior + return; + } + if(storedGames >= MAX_VARIATIONS-1) return; + + // push current tail of game on stack + savedResult[storedGames] = gameInfo.result; + savedDetails[storedGames] = gameInfo.resultDetails; + gameInfo.resultDetails = NULL; + savedFirst[storedGames] = firstMove; + savedLast [storedGames] = lastMove; + savedFramePtr[storedGames] = framePtr; + framePtr -= nrMoves; // reserve space for the boards + for(i=nrMoves; i>=1; i--) { // copy boards to stack, working downwards, in case of overlap + CopyBoard(boards[framePtr+i], boards[firstMove+i]); + for(j=0; j