Fix spurious reading of old game title by JAWS
[xboard.git] / backend.c
index b962510..cd53ac6 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -516,6 +516,13 @@ ChessSquare  KnightmateArray[2][BOARD_FILES] = {
         BlackUnicorn, BlackBishop, BlackMan, BlackRook }
 };
 
+ChessSquare SpartanArray[2][BOARD_FILES] = {
+    { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
+        WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
+    { BlackAlfil, BlackMarshall, BlackKing, BlackDragon,
+        BlackDragon, BlackKing, BlackAngel, BlackAlfil }
+};
+
 ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
         WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
@@ -955,6 +962,7 @@ InitBackEnd1()
       case VariantSuper:      /* experimental */
       case VariantGreat:      /* experimental, requires legality testing to be off */
       case VariantSChess:     /* S-Chess, should work */
+      case VariantSpartan:    /* should work */
        break;
       }
     }
@@ -4991,6 +4999,9 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, f
     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;
+    strncat(moveList[endPV-1], "\n", MOVE_LEN);
     if(storeComments)
        CoordsToAlgebraic(boards[endPV - 1],
                             PosFlags(endPV - 1),
@@ -5410,6 +5421,10 @@ InitPosition(redraw)
       pieces = KnightmateArray;
       SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k.");
       break;
+    case VariantSpartan:
+      pieces = SpartanArray;
+      SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k");
+      break;
     case VariantFairy:
       pieces = fairyArray;
       SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
@@ -5480,7 +5495,7 @@ InitPosition(redraw)
         if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue;
         initialPosition[0][j] = pieces[0][j-gameInfo.holdingsWidth];
         initialPosition[pawnRow][j] = WhitePawn;
-        initialPosition[BOARD_HEIGHT-pawnRow-1][j] = BlackPawn;
+        initialPosition[BOARD_HEIGHT-pawnRow-1][j] = gameInfo.variant == VariantSpartan ? BlackLance : BlackPawn;
         if(gameInfo.variant == VariantXiangqi) {
             if(j&1) {
                 initialPosition[pawnRow][j] =
@@ -5665,6 +5680,12 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice)
         promotionZoneSize = 3;
     }
 
+    // Treat Lance as Pawn when it is not representing Amazon
+    if(gameInfo.variant != VariantSuper) {
+        if(piece == WhiteLance) piece = WhitePawn; else
+        if(piece == BlackLance) piece = BlackPawn;
+    }
+
     // next weed out all moves that do not touch the promotion zone at all
     if((int)piece >= BlackPawn) {
         if(toY >= promotionZoneSize && fromY >= promotionZoneSize)
@@ -8340,6 +8361,7 @@ ParseGameHistory(game)
                if (q != NULL) *q = NULLCHAR;
                p++;
            }
+           while(q = strchr(p, '\n')) *q = ' '; // [HGM] crush linefeeds in result message
            gameInfo.resultDetails = StrSave(p);
            continue;
        }
@@ -8478,9 +8500,9 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
         board[toY][toX] = king;
         board[toY][toX+1] = board[fromY][BOARD_LEFT];
         board[fromY][BOARD_LEFT] = EmptySquare;
-    } else if (board[fromY][fromX] == WhitePawn
+    } else if ((board[fromY][fromX] == WhitePawn && gameInfo.variant != VariantXiangqi ||
+                board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi)
                && toY >= BOARD_HEIGHT-promoRank
-               && gameInfo.variant != VariantXiangqi
                ) {
        /* white pawn promotion */
         board[toY][toX] = CharToPiece(ToUpper(promoChar));
@@ -8542,9 +8564,9 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
        board[toY][toX] = BlackKing;
        board[fromY][0] = EmptySquare;
        board[toY][2] = BlackRook;
-    } else if (board[fromY][fromX] == BlackPawn
+    } else if ((board[fromY][fromX] == BlackPawn && gameInfo.variant != VariantXiangqi ||
+                board[fromY][fromX] == BlackLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi)
               && toY < promoRank
-               && gameInfo.variant != VariantXiangqi
                ) {
        /* black pawn promotion */
        board[toY][toX] = CharToPiece(ToLower(promoChar));
@@ -9606,7 +9628,7 @@ AutoPlayGameLoop()
          return;
        if (matchMode || appData.timeDelay == 0)
          continue;
-       if (appData.timeDelay < 0 || gameMode == AnalyzeFile)
+       if (appData.timeDelay < 0)
          return;
        StartLoadGameTimer((long)(1000.0 * appData.timeDelay));
        break;
@@ -9623,10 +9645,18 @@ AutoPlayOneMove()
       fprintf(debugFP, "AutoPlayOneMove(): current %d\n", currentMove);
     }
 
-    if (gameMode != PlayFromGameFile)
+    if (gameMode != PlayFromGameFile && gameMode != AnalyzeFile)
       return FALSE;
 
+    if (gameMode == AnalyzeFile && currentMove > backwardMostMove) {
+      pvInfoList[currentMove].depth = programStats.depth;
+      pvInfoList[currentMove].score = programStats.score;
+      pvInfoList[currentMove].time  = 0;
+      if(currentMove < forwardMostMove) AppendComment(currentMove+1, lastPV[0], 2);
+    }
+
     if (currentMove >= forwardMostMove) {
+      if(gameMode == AnalyzeFile) { ExitAnalyzeMode(); SendToProgram("force\n", &first); }
       gameMode = EditGame;
       ModeHighlight();
 
@@ -9759,6 +9789,7 @@ LoadGameOneMove(readAhead)
            if (q != NULL) *q = NULLCHAR;
            p++;
        }
+       while(q = strchr(p, '\n')) *q = ' '; // [HGM] crush linefeeds in result message
        GameEnds(moveType, p, GE_FILE);
        done = TRUE;
        if (cmailMsgLoaded) {
@@ -11631,7 +11662,7 @@ void
 EditTagsEvent()
 {
     char *tags = PGNTags(&gameInfo);
-    EditTagsPopUp(tags);
+    EditTagsPopUp(tags, NULL);
     free(tags);
 }
 
@@ -13292,7 +13323,7 @@ ReplaceComment(index, text)
 
     if(index && sscanf(text, "%f/%d", &score, &len) == 2 && 
        pvInfoList[index-1].depth == len &&
-       pvInfoList[index-1].score == (int) (score*100 + 0.5) &&
+       fabs(pvInfoList[index-1].score - score*100.) < 0.5 &&
        (p = strchr(text, '\n'))) text = p; // [HGM] strip off first line with PV info, if any
     while (*text == '\n') text++;
     len = strlen(text);
@@ -13367,24 +13398,24 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces);
        safeStrCpy(commentList[index], old, oldlen + len + 6);
        free(old);
        // [HGM] braces: join "{A\n}\n" + "{\nB}" as "{A\nB\n}"
-       if(commentList[index][oldlen-1] == '}' && (text[0] == '{' || addBraces)) {
-         if(addBraces) addBraces = FALSE; else { text++; len--; }
+       if(commentList[index][oldlen-1] == '}' && (text[0] == '{' || addBraces == TRUE)) {
+         if(addBraces == TRUE) addBraces = FALSE; else { text++; len--; }
          while (*text == '\n') { text++; len--; }
          commentList[index][--oldlen] = NULLCHAR;
       }
-       if(addBraces) strcat(commentList[index], "\n{\n");
+       if(addBraces) strcat(commentList[index], addBraces == 2 ? "\n(" : "\n{\n");
        else          strcat(commentList[index], "\n");
        strcat(commentList[index], text);
-       if(addBraces) strcat(commentList[index], "\n}\n");
+       if(addBraces) strcat(commentList[index], addBraces == 2 ? ")\n" : "\n}\n");
        else          strcat(commentList[index], "\n");
     } else {
        commentList[index] = (char *) malloc(len + 6); // perhaps wastes 4...
        if(addBraces)
-         safeStrCpy(commentList[index], "{\n", 3);
+         safeStrCpy(commentList[index], addBraces == 2 ? "(" : "{\n", 3);
        else commentList[index][0] = NULLCHAR;
        strcat(commentList[index], text);
-       strcat(commentList[index], "\n");
-       if(addBraces) strcat(commentList[index], "}\n");
+       strcat(commentList[index], addBraces == 2 ? ")\n" : "\n");
+       if(addBraces == TRUE) strcat(commentList[index], "}\n");
     }
 }
 
@@ -13403,7 +13434,7 @@ static char * FindStr( char * text, char * sub_text )
 /* [HGM] PV time: and then remove it, to prevent it appearing twice */
 char *GetInfoFromComment( int index, char * text )
 {
-    char * sep = text;
+    char * sep = text, *p;
 
     if( text != NULL && index > 0 ) {
         int score = 0;
@@ -13441,11 +13472,20 @@ char *GetInfoFromComment( int index, char * text )
                 return text;
             }
 
+            p = text;
+            if(p[1] == '(') { // comment starts with PV
+               p = strchr(p, ')'); // locate end of PV
+               if(p == NULL || sep < p+5) return text;
+               // at this point we have something like "{(.*) +0.23/6 ..."
+               p = text; while(*++p != ')') p[-1] = *p; p[-1] = ')';
+               *p = '\n'; while(*p == ' ' || *p == '\n') p++; *--p = '{';
+               // we now moved the brace to behind the PV: "(.*) {+0.23/6 ..."
+            }
             time = -1; sec = -1; deci = -1;
-            if( sscanf( text+1, "%d.%d/%d %d:%d", &score, &score_lo, &depth, &time, &sec ) != 5 &&
-               sscanf( text+1, "%d.%d/%d %d.%d", &score, &score_lo, &depth, &time, &deci ) != 5 &&
-                sscanf( text+1, "%d.%d/%d %d", &score, &score_lo, &depth, &time ) != 4 &&
-                sscanf( text+1, "%d.%d/%d", &score, &score_lo, &depth ) != 3   ) {
+            if( sscanf( p+1, "%d.%d/%d %d:%d", &score, &score_lo, &depth, &time, &sec ) != 5 &&
+               sscanf( p+1, "%d.%d/%d %d.%d", &score, &score_lo, &depth, &time, &deci ) != 5 &&
+                sscanf( p+1, "%d.%d/%d %d", &score, &score_lo, &depth, &time ) != 4 &&
+                sscanf( p+1, "%d.%d/%d", &score, &score_lo, &depth ) != 3   ) {
                 return text;
             }
 
@@ -13461,7 +13501,7 @@ char *GetInfoFromComment( int index, char * text )
             /* [HGM] PV time: now locate end of PV info */
             while( *++sep >= '0' && *sep <= '9'); // strip depth
             if(time >= 0)
-            while( *++sep >= '0' && *sep <= '9'); // strip time
+            while( *++sep >= '0' && *sep <= '9' || *sep == '\n'); // strip time
             if(sec >= 0)
             while( *++sep >= '0' && *sep <= '9'); // strip seconds
             if(deci >= 0)
@@ -13481,6 +13521,7 @@ char *GetInfoFromComment( int index, char * text )
         pvInfoList[index-1].score = score;
         pvInfoList[index-1].time  = 10*time; // centi-sec
         if(*sep == '}') *sep = 0; else *--sep = '{';
+        if(p != text) { while(*p++ = *sep++); sep = text; } // squeeze out space between PV and comment, and return both
     }
     return sep;
 }