Add option -absoluteAnalysisScores
[xboard.git] / backend.c
index 2658402..d14530f 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5244,7 +5244,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
 Boolean pushed = FALSE;
 
 void
-ParsePV(char *pv, Boolean storeComments)
+ParsePV(char *pv, Boolean storeComments, Boolean atEnd)
 { // Parse a string of PV moves, and append to current game, behind forwardMostMove
   int fromX, fromY, toX, toY; char promoChar;
   ChessMove moveType;
@@ -5293,45 +5293,56 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, f
     endPV++;
     CopyBoard(boards[endPV], boards[endPV-1]);
     ApplyMove(fromX, fromY, toX, toY, promoChar, boards[endPV]);
-    moveList[endPV-1][0] = fromX + AAA;
-    moveList[endPV-1][1] = fromY + ONE;
-    moveList[endPV-1][2] = toX + AAA;
-    moveList[endPV-1][3] = toY + ONE;
-    moveList[endPV-1][4] = promoChar;
-    moveList[endPV-1][5] = NULLCHAR;
+    CoordsToComputerAlgebraic(fromY, fromX, toY, toX, promoChar, moveList[endPV - 1]);
     strncat(moveList[endPV-1], "\n", MOVE_LEN);
-    if(storeComments)
-       CoordsToAlgebraic(boards[endPV - 1],
+    CoordsToAlgebraic(boards[endPV - 1],
                             PosFlags(endPV - 1),
                             fromY, fromX, toY, toX, promoChar,
                             parseList[endPV - 1]);
-    else
-       parseList[endPV-1][0] = NULLCHAR;
   } while(valid);
-  currentMove = endPV;
+  currentMove = (atEnd || endPV == forwardMostMove) ? endPV : forwardMostMove + 1;
   if(currentMove == forwardMostMove) ClearPremoveHighlights(); else
   SetPremoveHighlights(moveList[currentMove-1][0]-AAA, moveList[currentMove-1][1]-ONE,
                        moveList[currentMove-1][2]-AAA, moveList[currentMove-1][3]-ONE);
   DrawPosition(TRUE, boards[currentMove]);
 }
 
+int
+MultiPV(ChessProgramState *cps)
+{      // check if engine supports MultiPV, and if so, return the number of the option that sets it
+       int i;
+       for(i=0; i<cps->nrOptions; i++)
+           if(!strcmp(cps->option[i].name, "MultiPV") && cps->option[i].type == Spin)
+               return i;
+       return -1;
+}
+
 Boolean
 LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
 {
-       int startPV;
-       char *p;
+       int startPV, multi, lineStart, origIndex = index;
+       char *p, buf2[MSG_SIZ];
 
        if(index < 0 || index >= strlen(buf)) return FALSE; // sanity
        lastX = x; lastY = y;
        while(index > 0 && buf[index-1] != '\n') index--; // beginning of line
-       startPV = index;
+       lineStart = startPV = index;
        while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index;
        if(index == startPV && (p = StrCaseStr(buf+index, "PV="))) startPV = p - buf + 3;
        index = startPV;
        do{ while(buf[index] && buf[index] != '\n') index++;
        } while(buf[index] == '\n' && buf[index+1] == '\\' && buf[index+2] == ' ' && index++); // join kibitzed PV continuation line
        buf[index] = 0;
-       ParsePV(buf+startPV, FALSE);
+       if(lineStart == 0 && gameMode == AnalyzeMode && (multi = MultiPV(&first)) >= 0) {
+               int n = first.option[multi].value;
+               if(origIndex > 17 && origIndex < 24) { if(n>1) n--; } else if(origIndex > index - 6) n++;
+               snprintf(buf2, MSG_SIZ, "option MultiPV=%d\n", n);
+               if(first.option[multi].value != n) SendToProgram(buf2, &first);
+               first.option[multi].value = n;
+               *start = *end = 0;
+               return FALSE;
+       }
+       ParsePV(buf+startPV, FALSE, gameMode != AnalyzeMode);
        *start = startPV; *end = index-1;
        return TRUE;
 }
@@ -5341,17 +5352,32 @@ LoadPV(int x, int y)
 { // called on right mouse click to load PV
   int which = gameMode == TwoMachinesPlay && (WhiteOnMove(forwardMostMove) == (second.twoMachinesColor[0] == 'w'));
   lastX = x; lastY = y;
-  ParsePV(lastPV[which], FALSE); // load the PV of the thinking engine in the boards array.
+  ParsePV(lastPV[which], FALSE, TRUE); // load the PV of the thinking engine in the boards array.
   return TRUE;
 }
 
 void
 UnLoadPV()
 {
+  int oldFMM = forwardMostMove; // N.B.: this was currentMove before PV was loaded!
   if(endPV < 0) return;
   endPV = -1;
+  if(gameMode == AnalyzeMode && currentMove > forwardMostMove) {
+       Boolean saveAnimate = appData.animate;
+       if(pushed) {
+           if(shiftKey && storedGames < MAX_VARIATIONS-2) { // wants to start variation, and there is space
+               if(storedGames == 1) GreyRevert(FALSE);      // we already pushed the tail, so just make it official
+           } else storedGames--; // abandon shelved tail of original game
+       }
+       pushed = FALSE;
+       forwardMostMove = currentMove;
+       currentMove = oldFMM;
+       appData.animate = FALSE;
+       ToNrEvent(forwardMostMove);
+       appData.animate = saveAnimate;
+  }
   currentMove = forwardMostMove;
-  if(pushed) { PopInner(0); pushed = FALSE; } // restore shelved game contnuation
+  if(pushed) { PopInner(0); pushed = FALSE; } // restore shelved game continuation
   ClearPremoveHighlights();
   DrawPosition(TRUE, boards[currentMove]);
 }
@@ -9250,6 +9276,7 @@ ShowMove(fromX, fromY, toX, toY)
     DrawPosition(FALSE, boards[currentMove]);
     DisplayBothClocks();
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
+    DisplayBook(currentMove);
 }
 
 void SendEgtPath(ChessProgramState *cps)
@@ -12311,6 +12338,7 @@ void
 EditTagsEvent()
 {
     char *tags = PGNTags(&gameInfo);
+    bookUp = FALSE;
     EditTagsPopUp(tags, NULL);
     free(tags);
 }
@@ -13491,6 +13519,7 @@ ForwardInner(target)
     if ( !matchMode && gameMode != Training) { // [HGM] PV info: routine tests if empty
        DisplayComment(currentMove - 1, commentList[currentMove]);
     }
+    DisplayBook(currentMove);
 }
 
 
@@ -13593,6 +13622,7 @@ BackwardInner(target)
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
     // [HGM] PV info: routine tests if comment empty
     DisplayComment(currentMove - 1, commentList[currentMove]);
+    DisplayBook(currentMove);
 }
 
 void
@@ -16244,7 +16274,7 @@ LoadVariation(int index, char *text)
        PushTail(currentMove, forwardMostMove); // shelve main variation. This truncates game
        // kludge: use ParsePV() to append variation to game
        move = currentMove;
-       ParsePV(start, TRUE);
+       ParsePV(start, TRUE, TRUE);
        forwardMostMove = endPV; endPV = -1; currentMove = move; // cleanup what ParsePV did
        ClearPremoveHighlights();
        CommentPopDown();