Fix display of uninitialized boards in background observe
[xboard.git] / backend.c
index 424463d..7a3c731 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -243,7 +243,11 @@ static int exiting = 0; /* [HGM] moved to top */
 static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/;
 int startedFromPositionFile = FALSE; Board filePosition;       /* [HGM] loadPos */
 Board partnerBoard;     /* [HGM] bughouse: for peeking at partner game          */
+Boolean partnerBoardValid = 0;
+char partnerStatus[MSG_SIZ];
 Boolean partnerUp;
+Boolean originalFlip;
+Boolean twoBoards = 0;
 char endingGame = 0;    /* [HGM] crash: flag to prevent recursion of GameEnds() */
 int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS     */
 VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
@@ -3461,6 +3465,7 @@ read_from_ics(isr, closure, data, count, error)
                        ZippyGameStart(whitename, blackname);
                    }
 #endif /*ZIPPY*/
+                   partnerBoardValid = FALSE; // [HGM] bughouse
                    continue;
                }
 
@@ -3501,6 +3506,7 @@ read_from_ics(isr, closure, data, count, error)
                    Reset(TRUE, TRUE);
                }
 #endif /*ZIPPY*/
+               if(appData.bgObserve && partnerBoardValid) DrawPosition(TRUE, partnerBoard);
                continue;
            }
 
@@ -3647,7 +3653,7 @@ read_from_ics(isr, closure, data, count, error)
                                    gameInfo.white, white_holding,
                                    gameInfo.black, black_holding);
                        }
-
+                       if(!partnerUp) // [HGM] bughouse: when peeking at partner game we already know what he captured...
                         DrawPosition(FALSE, boards[currentMove]);
                        DisplayTitle(str);
                      } else if(appData.bgObserve) { // [HGM] bughouse: holdings of other game => background
@@ -3659,7 +3665,9 @@ read_from_ics(isr, closure, data, count, error)
                         /* [HGM] copy holdings to partner-board holdings area */
                         CopyHoldings(partnerBoard, white_holding, WhitePawn);
                         CopyHoldings(partnerBoard, black_holding, BlackPawn);
+                        if(twoBoards) { partnerUp = 1; flipView = !flipView; } // [HGM] dual: always draw
                         if(partnerUp) DrawPosition(FALSE, partnerBoard);
+                        if(twoBoards) { partnerUp = 0; flipView = !flipView; DrawPosition(TRUE, boards[currentMove]); } // [HGM] dual: redraw own
                      }
                    }
                    /* Suppress following prompt */
@@ -3813,7 +3821,6 @@ ParseBoard12(string)
     if((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack)
         && newGameMode == IcsObserving && appData.bgObserve) {
       // [HGM] bughouse: don't act on alien boards while we play. Just parse the board and save it */
-      char buf[MSG_SIZ];
       for (k = 0; k < ranks; k++) {
         for (j = 0; j < files; j++)
           board[k][j+gameInfo.holdingsWidth] = CharToPiece(board_chars[(ranks-1-k)*(files+1) + j]);
@@ -3822,11 +3829,14 @@ ParseBoard12(string)
              board[k][1] = board[k][BOARD_WIDTH-2] = (ChessSquare) 0;;
         }
       }
+      if(appData.dualBoard) { twoBoards = partnerUp = 1; flipView = !flipView; InitDrawingSizes(-2,0); } // [HGM] dual
       CopyBoard(partnerBoard, board);
       if(partnerUp) DrawPosition(FALSE, partnerBoard);
-      sprintf(buf, "W: %d:%d B: %d:%d (%d-%d) %c", white_time/60000, (white_time%60000)/1000,
+      if(twoBoards) { partnerUp = 0; flipView = !flipView; DrawPosition(TRUE, boards[currentMove]); } // [HGM] dual: redraw own game!
+      sprintf(partnerStatus, "W: %d:%d B: %d:%d (%d-%d) %c", white_time/60000, (white_time%60000)/1000,
                 (black_time/60000), (black_time%60000)/1000, white_stren, black_stren, to_play);
-      DisplayMessage(buf, "");
+      DisplayMessage(partnerStatus, "");
+       partnerBoardValid = TRUE;
       return;
     }
 
@@ -4359,6 +4369,7 @@ ParseBoard12(string)
              ClearPremoveHighlights();
 
       j = seekGraphUp; seekGraphUp = FALSE; // [HGM] seekgraph: when we draw a board, it overwrites the seek graph
+       if(partnerUp) { flipView = originalFlip; partnerUp = FALSE; j = TRUE; } // [HGM] bughouse: restore view
       DrawPosition(j, boards[currentMove]);
 
       DisplayMove(moveNum - 1);
@@ -4715,6 +4726,8 @@ AlphaRank(char *move, int n)
     }
 }
 
+char yy_textstr[8000];
+
 /* Parser for moves from gnuchess, ICS, or user typein box */
 Boolean
 ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
@@ -4727,7 +4740,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
     if (appData.debugMode) {
         fprintf(debugFP, "move to parse: %s\n", move);
     }
-    *moveType = yylexstr(moveNum, move);
+    *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
 
     switch (*moveType) {
       case WhitePromotionChancellor:
@@ -4821,15 +4834,15 @@ ParsePV(char *pv, Boolean storeComments)
   int fromX, fromY, toX, toY; char promoChar;
   ChessMove moveType;
   Boolean valid;
-  int nr = 0, dummy;
+  int nr = 0;
 
   endPV = forwardMostMove;
   do {
-    while(*pv == ' ') pv++;
-    if(nr == 0 && *pv == '(') pv++; // first (ponder) move can be in parentheses
+    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
     valid = ParseOneMove(pv, endPV, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
 if(appData.debugMode){
-fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, pv);
+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);
 }
     if(!valid && nr == 0 &&
        ParseOneMove(pv, endPV-1, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)){ 
@@ -4848,30 +4861,13 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+
           strcpy(moveList[endPV-2], "_0_0"); // suppress premove highlight on takeback move
         }
       }
-    if(moveType == Comment) {
-       // [HGM] vari: try to skip comment
-       int level = 0; char c, *start = pv, wait = NULLCHAR;
-       do {
-           if(!wait) {
-               if(*pv == '(') level++; else
-               if(*pv == ')' && level) level--;
-           }
-           if(*pv == wait) wait = NULLCHAR; else
-           if(*pv == '{') wait = '}'; else
-           if(*pv == '[') wait = ']';
-           pv++;
-       } while(*pv && (wait || level));
-       if(storeComments) {
-         c = *pv; *pv = NULLCHAR;
-         AppendComment(endPV, start, FALSE);
-         *pv = c;
-       }
-      valid++; // allow comments in PV
+    pv = strstr(pv, yy_textstr) + strlen(yy_textstr); // skip what we parsed
+    if(nr == 0 && !storeComments && *pv == ')') pv++; // closing parenthesis of ponder move;
+    if(moveType == Comment && storeComments) AppendComment(endPV, yy_textstr, FALSE);
+    if(moveType == Comment || moveType == NAG || moveType == ElapsedTime) {
+       valid++; // allow comments in PV
        continue;
     }
-    if(sscanf(pv, "%d...", &dummy) == 1 || sscanf(pv, "%d.", &dummy) == 1)
-       while(*pv && *pv++ != ' '); // skip any move numbers
-    while(*pv && *pv++ != ' '); // skip what we parsed; assume space separators
     nr++;
     if(endPV+1 > framePtr) break; // no space, truncate
     if(!valid) break;
@@ -4903,14 +4899,17 @@ Boolean
 LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
 {
        int startPV;
+       char *p;
 
        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;
-      while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index;
-      index = startPV;
-       while(buf[index] && buf[index] != '\n') 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);
        *start = startPV; *end = index-1;
@@ -6448,8 +6447,19 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
 
     if((gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack)
         && !appData.zippyPlay && appData.bgObserve) { // [HGM] bughouse: show background game
-       if(action == Press)   { flipView = !flipView; DrawPosition(TRUE, partnerBoard); partnerUp = TRUE; } else
-       if(action == Release) { flipView = !flipView; DrawPosition(TRUE, boards[currentMove]); partnerUp = FALSE; }
+       if(!partnerBoardValid) return -2; // suppress display of uninitialized boards
+       if( appData.dualBoard) return -2; // [HGM] dual: is already displayed
+       if(action == Press)   {
+           originalFlip = flipView;
+           flipView = !flipView; // temporarily flip board to see game from partners perspective
+           DrawPosition(TRUE, partnerBoard);
+           DisplayMessage(partnerStatus, "");
+           partnerUp = TRUE;
+       } else if(action == Release) {
+           flipView = originalFlip;
+           DrawPosition(TRUE, boards[currentMove]);
+           partnerUp = FALSE;
+       }
        return -2;
     }
 
@@ -8894,6 +8904,7 @@ GameEnds(result, resultDetails, whosays)
 
     if(endingGame) return; /* [HGM] crash: forbid recursion */
     endingGame = 1;
+    if(twoBoards) { twoBoards = partnerUp = 0; InitDrawingSizes(-2, 0); } // [HGM] dual
 
     if (appData.debugMode) {
       fprintf(debugFP, "GameEnds(%d, %s, %d)\n",