Add -fSAN / -sSAN options
authorH.G. Muller <h.g.muller@hccnet.nl>
Sun, 19 Jun 2011 12:28:09 +0000 (14:28 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 21 Jun 2011 10:07:07 +0000 (12:07 +0200)
These options force the PV of the applicable engine to be converted to SAN.
They make use of the existing ParsePV routine, after shelfing a possible
PV (from user PV walking) to free the space after the last move.
Could be costly in terms of CPU usage.

args.h
backend.c
common.h

diff --git a/args.h b/args.h
index 60a04a5..fa69cb0 100644 (file)
--- a/args.h
+++ b/args.h
@@ -103,7 +103,7 @@ IcsTextMenuEntry icsTextMenuEntry[ICS_TEXT_MENU_SIZE];
 
 int junk;
 Boolean singleList;
-char *homeDir;\r
+char *homeDir;
 
 void EnsureOnScreen(int *x, int *y, int minX, int minY);
 char StringGet(void *getClosure);
@@ -622,6 +622,8 @@ ArgDescriptor argDescriptors[] = {
   { "secondPgnName", ArgString, (void *) &appData.pgnName[1], FALSE, (ArgIniType) "" },
   { "sn", ArgString, (void *) &appData.pgnName[1], FALSE, INVALID },
   { "absoluteAnalysisScores", ArgBoolean, (void *) &appData.whitePOV, TRUE, FALSE },
+  { "fSAN", ArgTrue, (void *) &appData.pvSAN[0], FALSE, FALSE },
+  { "sSAN", ArgTrue, (void *) &appData.pvSAN[1], FALSE, FALSE },
   { "pairingEngine", ArgFilename, (void *) &appData.pairingEngine, TRUE, "" },
   { "defaultTourneyName", ArgFilename, (void *) &appData.defName, TRUE, "" },
 
index 6520238..f028af4 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1451,7 +1451,7 @@ MatchEvent(int mode)
        }
        matchMode = mode;
        matchGame = roundNr = 1;
-       first.matchWins = second.matchWins = 0; // [HGM] match: needed in later matches\r
+       first.matchWins = second.matchWins = 0; // [HGM] match: needed in later matches
        NextMatchGame();
 }
 
@@ -5276,6 +5276,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
 }
 
 Boolean pushed = FALSE;
+char *lastParseAttempt;
 
 void
 ParsePV(char *pv, Boolean storeComments, Boolean atEnd)
@@ -5293,6 +5294,7 @@ ParsePV(char *pv, Boolean storeComments, Boolean atEnd)
   do {
     while(*pv == ' ' || *pv == '\n' || *pv == '\t') pv++; // must still read away whitespace
     if(nr == 0 && !storeComments && *pv == '(') pv++; // first (ponder) move can be in parentheses
+    lastParseAttempt = pv;
     valid = ParseOneMove(pv, endPV, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
 if(appData.debugMode){
 fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, yy_textstr, pv);
@@ -5334,6 +5336,7 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, f
                             fromY, fromX, toY, toX, promoChar,
                             parseList[endPV - 1]);
   } while(valid);
+  if(atEnd == 2) return; // used hidden, for PV conversion
   currentMove = (atEnd || endPV == forwardMostMove) ? endPV : forwardMostMove + 1;
   if(currentMove == forwardMostMove) ClearPremoveHighlights(); else
   SetPremoveHighlights(moveList[currentMove-1][0]-AAA, moveList[currentMove-1][1]-ONE,
@@ -5381,6 +5384,25 @@ LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
        return TRUE;
 }
 
+char *
+PvToSAN(char *pv)
+{
+       static char buf[10*MSG_SIZ];
+       int i, k=0, savedEnd=endPV;
+       *buf = NULLCHAR;
+       if(forwardMostMove < endPV) PushInner(forwardMostMove, endPV);
+       ParsePV(pv, FALSE, 2); // this appends PV to game, suppressing any display of it
+       for(i = forwardMostMove; i<endPV; i++){
+           if(i&1) snprintf(buf+k, 10*MSG_SIZ-k, "%s ", parseList[i]);
+           else    snprintf(buf+k, 10*MSG_SIZ-k, "%d. %s ", i/2 + 1, parseList[i]);
+           k += strlen(buf+k);
+       }
+       snprintf(buf+k, 10*MSG_SIZ-k, "%s", lastParseAttempt); // if we ran into stuff that could not be parsed, print it verbatim
+       if(forwardMostMove < savedEnd) PopInner(0);
+       endPV = savedEnd;
+       return buf;
+}
+
 Boolean
 LoadPV(int x, int y)
 { // called on right mouse click to load PV
@@ -7060,16 +7082,16 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
     if (action != Press) return -2; // return code to be ignored
     switch (gameMode) {
       case IcsExamining:
-       if(xSqr < BOARD_LEFT || xSqr >= BOARD_RGHT) return -1;\r
+       if(xSqr < BOARD_LEFT || xSqr >= BOARD_RGHT) return -1;
       case EditPosition:
-       if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;\r
+       if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;
        if (xSqr < 0 || ySqr < 0) return -1;
        if(appData.pieceMenu) { whichMenu = 0; break; } // edit-position menu
        pieceSweep = shiftKey ? BlackPawn : WhitePawn;  // [HGM] sweep: prepare selecting piece by mouse sweep
        toX = xSqr; toY = ySqr; lastX = x, lastY = y;
        if(flipView) toX = BOARD_WIDTH - 1 - toX; else toY = BOARD_HEIGHT - 1 - toY;
        NextPiece(0);
-       return -2;\r
+       return -2;
       case IcsObserving:
        if(!appData.icsEngineAnalyze) return -1;
       case IcsPlayingWhite:
@@ -7667,7 +7689,7 @@ HandleMachineMove(message, cps)
     int fromX, fromY, toX, toY;
     ChessMove moveType;
     char promoChar;
-    char *p;
+    char *p, *pv=buf1;
     int machineWhite;
     char *bookHit;
 
@@ -8524,6 +8546,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                     curscore = -curscore;
                 }
 
+               if(appData.pvSAN[cps==&second]) pv = PvToSAN(buf1);
 
                tempStats.depth = plylev;
                tempStats.nodes = nodes;
@@ -8545,15 +8568,15 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                }
 
                /* Buffer overflow protection */
-               if (buf1[0] != NULLCHAR) {
-                   if (strlen(buf1) >= sizeof(tempStats.movelist)
+               if (pv[0] != NULLCHAR) {
+                   if (strlen(pv) >= sizeof(tempStats.movelist)
                        && appData.debugMode) {
                        fprintf(debugFP,
                                "PV is too long; using the first %u bytes.\n",
                                (unsigned) sizeof(tempStats.movelist) - 1);
                    }
 
-                    safeStrCpy( tempStats.movelist, buf1, sizeof(tempStats.movelist)/sizeof(tempStats.movelist[0]) );
+                    safeStrCpy( tempStats.movelist, pv, sizeof(tempStats.movelist)/sizeof(tempStats.movelist[0]) );
                } else {
                    sprintf(tempStats.movelist, " no PV\n");
                }
@@ -8590,14 +8613,14 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                 if( buf1[0] != NULLCHAR ) {
                     unsigned max_len = sizeof(thinkOutput) - strlen(thinkOutput) - 1;
 
-                    if( strlen(buf1) > max_len ) {
+                    if( strlen(pv) > max_len ) {
                        if( appData.debugMode) {
                            fprintf(debugFP,"PV is too long for thinkOutput, truncating.\n");
                         }
-                        buf1[max_len+1] = '\0';
+                        pv[max_len+1] = '\0';
                     }
 
-                    strcat( thinkOutput, buf1 );
+                    strcat( thinkOutput, pv);
                 }
 
                 if (currentMove == forwardMostMove || gameMode == AnalyzeMode
@@ -9718,6 +9741,7 @@ void SwapEngines(int n)
     SWAP(timeOdds, h)
     SWAP(logo, p)
     SWAP(pgnName, p)
+    SWAP(pvSAN, h)
 }
 
 void
@@ -15035,14 +15059,14 @@ AskQuestionEvent(title, question, replyPrefix, which)
 void
 TypeInEvent(char firstChar)
 {
-    if ((gameMode == BeginningOfGame && !appData.icsActive) || \r
-        gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||\r
-       gameMode == AnalyzeMode || gameMode == EditGame || \r
-       gameMode == EditPosition || gameMode == IcsExamining ||\r
-       gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
-       isdigit(firstChar) && // [HGM] movenum: allow typing in of move nr in 'passive' modes\r
-               ( gameMode == AnalyzeFile || gameMode == PlayFromGameFile ||\r
-                 gameMode == IcsObserving || gameMode == TwoMachinesPlay    ) ||\r
+    if ((gameMode == BeginningOfGame && !appData.icsActive) || 
+        gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||
+       gameMode == AnalyzeMode || gameMode == EditGame || 
+       gameMode == EditPosition || gameMode == IcsExamining ||
+       gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
+       isdigit(firstChar) && // [HGM] movenum: allow typing in of move nr in 'passive' modes
+               ( gameMode == AnalyzeFile || gameMode == PlayFromGameFile ||
+                 gameMode == IcsObserving || gameMode == TwoMachinesPlay    ) ||
        gameMode == Training) PopUpMoveDialog(firstChar);
 }
 
@@ -15052,34 +15076,34 @@ TypeInDoneEvent(char *move)
        Board board;
        int n, fromX, fromY, toX, toY;
        char promoChar;
-       ChessMove moveType;\r
-
-       // [HGM] FENedit\r
-       if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {\r
-               EditPositionPasteFEN(move);\r
-               return;\r
-       }\r
-       // [HGM] movenum: allow move number to be typed in any mode\r
-       if(sscanf(move, "%d", &n) == 1 && n != 0 ) {\r
-         ToNrEvent(2*n-1);\r
-         return;\r
-       }\r
-
-      if (gameMode != EditGame && currentMove != forwardMostMove && \r
-       gameMode != Training) {\r
-       DisplayMoveError(_("Displayed move is not current"));\r
-      } else {\r
-       int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
-         &moveType, &fromX, &fromY, &toX, &toY, &promoChar);\r
-       if(!ok && move[0] >= 'a') { move[0] += 'A' - 'a'; ok = 2; } // [HGM] try also capitalized\r
-       if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
-         &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {\r
-         UserMoveEvent(fromX, fromY, toX, toY, promoChar);     \r
-       } else {\r
-         DisplayMoveError(_("Could not parse move"));\r
-       }
-      }\r
-}\r
+       ChessMove moveType;
+
+       // [HGM] FENedit
+       if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {
+               EditPositionPasteFEN(move);
+               return;
+       }
+       // [HGM] movenum: allow move number to be typed in any mode
+       if(sscanf(move, "%d", &n) == 1 && n != 0 ) {
+         ToNrEvent(2*n-1);
+         return;
+       }
+
+      if (gameMode != EditGame && currentMove != forwardMostMove && 
+       gameMode != Training) {
+       DisplayMoveError(_("Displayed move is not current"));
+      } else {
+       int ok = ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, 
+         &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
+       if(!ok && move[0] >= 'a') { move[0] += 'A' - 'a'; ok = 2; } // [HGM] try also capitalized
+       if (ok==1 || ok && ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, 
+         &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {
+         UserMoveEvent(fromX, fromY, toX, toY, promoChar);     
+       } else {
+         DisplayMoveError(_("Could not parse move"));
+       }
+      }
+}
 
 void
 DisplayMove(moveNumber)
index ad52fb9..fadc73d 100644 (file)
--- a/common.h
+++ b/common.h
@@ -648,6 +648,7 @@ typedef struct {
     Boolean pieceMenu;
     Boolean sweepSelect;
     Boolean whitePOV;
+    Boolean pvSAN[ENGINES];
 
     char *tourneyFile;
     char *defName;