Fix edit command for double-digit ranks
[xboard.git] / backend.c
index f1dcf5d..bca59d4 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5956,7 +5956,7 @@ ptclen (const char *s, char *escapes)
 {
     int n = 0;
     if(!*escapes) return strlen(s);
-    while(*s) n += (*s != ':' && !strchr(escapes, *s)), s++;
+    while(*s) n += (*s != '/' && !strchr(escapes, *s)), s++;
     return n;
 }
 
@@ -5965,25 +5965,25 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
 /* [HGM] moved here from winboard.c because of its general usefulness */
 /*       Basically a safe strcpy that uses the last character as King */
 {
-    int result = FALSE; int NrPieces;
+    int result = FALSE; int NrPieces, offs;
 
     if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare
                     && NrPieces >= 12 && !(NrPieces&1)) {
         int i, j = 0; /* [HGM] Accept even length from 12 to 88 */
 
         for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
-        for( i=0; i<NrPieces/2-1; i++ ) {
+        for( i=offs=0; i<NrPieces/2-1; i++ ) {
             char *p;
-            if(map[j] == ':' && *escapes) i = CHUPROMOTED WhitePawn, j++;
-            table[i] = map[j++];
-            if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
+            if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+            table[i + offs] = map[j++];
+            if(p = strchr(escapes, map[j])) j++, table[i + offs] += 64*(p - escapes + 1);
         }
         table[(int) WhiteKing]  = map[j++];
-        for( i=0; i<NrPieces/2-1; i++ ) {
+        for( i=offs=0; i<NrPieces/2-1; i++ ) {
             char *p;
-            if(map[j] == ':' && *escapes) i = CHUPROMOTED WhitePawn, j++;
-            table[WHITE_TO_BLACK i] = map[j++];
-            if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i] += 64*(p - escapes + 1);
+            if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+            table[WHITE_TO_BLACK i + offs] = map[j++];
+            if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i + offs] += 64*(p - escapes + 1);
         }
         table[(int) BlackKing]  = map[j++];
 
@@ -6172,8 +6172,8 @@ InitPosition (int redraw)
       gameInfo.boardWidth  = 12;
       gameInfo.boardHeight = 12;
       nrCastlingRights = 0;
-      SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN:+.++.++++++++++.+++++K"
-                                   "p.brqsexogcathd.vmlifn:+.++.++++++++++.+++++k", SUFFIXES);
+      SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/+.++.++++++++++.+++++K"
+                                   "p.brqsexogcathd.vmlifn/+.++.++++++++++.+++++k", SUFFIXES);
       break;
     case VariantCourier:
       pieces = CourierArray;
@@ -6399,11 +6399,11 @@ SendBoard (ChessProgramState *cps, int moveNum)
          if ((int) *bp < (int) BlackPawn) {
            if(j == BOARD_RGHT+1)
                 snprintf(message, MSG_SIZ, "%c@%d\n", PieceToChar(*bp), bp[-1]);
-           else snprintf(message, MSG_SIZ, "%c%c%c\n", PieceToChar(*bp), AAA + j, ONE + i);
+           else snprintf(message, MSG_SIZ, "%c%c%d\n", PieceToChar(*bp), AAA + j, ONE + i - '0');
             if(message[0] == '+' || message[0] == '~') {
-             snprintf(message, MSG_SIZ,"%c%c%c+\n",
+             snprintf(message, MSG_SIZ,"%c%c%d+\n",
                         PieceToChar((ChessSquare)(DEMOTED *bp)),
-                        AAA + j, ONE + i);
+                        AAA + j, ONE + i - '0');
             }
             if(cps->alphaRank) { /* [HGM] shogi: translate coords */
                 message[1] = BOARD_RGHT   - 1 - j + '1';
@@ -6423,12 +6423,12 @@ SendBoard (ChessProgramState *cps, int moveNum)
              && ((int) *bp >= (int) BlackPawn)) {
            if(j == BOARD_LEFT-2)
                 snprintf(message, MSG_SIZ, "%c@%d\n", ToUpper(PieceToChar(*bp)), bp[1]);
-           else snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
-                    AAA + j, ONE + i);
+           else snprintf(message,MSG_SIZ, "%c%c%d\n", ToUpper(PieceToChar(*bp)),
+                    AAA + j, ONE + i - '0');
             if(message[0] == '+' || message[0] == '~') {
-             snprintf(message, MSG_SIZ,"%c%c%c+\n",
+             snprintf(message, MSG_SIZ,"%c%c%d+\n",
                         PieceToChar((ChessSquare)(DEMOTED *bp)),
-                        AAA + j, ONE + i);
+                        AAA + j, ONE + i - '0');
             }
             if(cps->alphaRank) { /* [HGM] shogi: translate coords */
                 message[1] = BOARD_RGHT   - 1 - j + '1';
@@ -8109,7 +8109,7 @@ Adjudicate (ChessProgramState *cps)
        // most tests only when we understand the game, i.e. legality-checking on
            if( appData.testLegality )
            {   /* [HGM] Some more adjudications for obstinate engines */
-               int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+1], i;
+               int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+2], i;
                static int moveCount = 6;
                ChessMove result;
                char *reason = NULL;
@@ -8980,10 +8980,10 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
     }
     if(sscanf(message, "piece %s %s", buf2, buf1) == 2) {
       ChessSquare piece = WhitePawn;
-      char *p=buf2, *q, *s = SUFFIXES, ID = *p;
+      char *p=message+6, *q, *s = SUFFIXES, ID = *p;
       if(*p == '+') piece = CHUPROMOTED WhitePawn, ID = *++p;
       if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++;
-      piece += CharToPiece(ID) - WhitePawn;
+      piece += CharToPiece(ID & 255) - WhitePawn;
       if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR
       /* always accept definition of  */       && piece != WhiteFalcon && piece != BlackFalcon
       /* wild-card pieces.            */       && piece != WhiteCobra  && piece != BlackCobra
@@ -8995,7 +8995,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
       if(piece < EmptySquare) {
         pieceDefs = TRUE;
         ASSIGN(pieceDesc[piece], buf1);
-        if(isupper(*p) && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); }
+        if((ID & 32) == 0 && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); }
       }
       return;
     }
@@ -9533,6 +9533,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            buf1[0] = NULLCHAR;
            if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",
                       &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) {
+               char score_buf[MSG_SIZ];
 
                if(nodes>>32 == u64Const(0xFFFFFFFF))   // [HGM] negative node count read
                    nodes += u64Const(0x100000000);
@@ -9633,11 +9634,17 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                     [AS] Protect the thinkOutput buffer from overflow... this
                     is only useful if buf1 hasn't overflowed first!
                 */
-               snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%+.2f %s%s",
+               if(curscore >= MATE_SCORE) 
+                   snprintf(score_buf, MSG_SIZ, "#%d", curscore - MATE_SCORE);
+               else if(curscore <= -MATE_SCORE) 
+                   snprintf(score_buf, MSG_SIZ, "#%d", curscore + MATE_SCORE);
+               else
+                   snprintf(score_buf, MSG_SIZ, "%+.2f", ((double) curscore) / 100.0);
+               snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%s %s%s",
                         plylev,
                         (gameMode == TwoMachinesPlay ?
                          ToUpper(cps->twoMachinesColor[0]) : ' '),
-                        ((double) curscore) / 100.0,
+                        score_buf,
                         prefixHint ? lastHint : "",
                         prefixHint ? " " : "" );
 
@@ -11413,16 +11420,17 @@ GameEnds (ChessMove result, char *resultDetails, int whosays)
               && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway
               && gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course...
               && result != GameIsDrawn)
-           {   int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
+           {   int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
                for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {
                        int p = (signed char)boards[forwardMostMove][i][j] - color;
                        if(p >= 0 && p <= (int)WhiteKing) k++;
+                       oppoKings += (p + color == WhiteKing + BlackPawn - color);
                }
                if (appData.debugMode) {
                     fprintf(debugFP, "GE(%d, %s, %d) bare king k=%d color=%d\n",
                        result, resultDetails ? resultDetails : "(null)", whosays, k, color);
                }
-               if(k <= 1) {
+               if(k <= 1 && oppoKings > 0) { // the latter needed in Atomic, where bare K wins if opponent King already destroyed
                        result = GameIsDrawn;
                        snprintf(buf, MSG_SIZ, "%s but bare king", resultDetails);
                        resultDetails = buf;
@@ -18086,7 +18094,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize)
     int i, j, k, w=0, subst=0, shuffle=0, wKingRank = -1, bKingRank = -1;
     char *p, c;
     int emptycount, virgin[BOARD_FILES];
-    ChessSquare piece;
+    ChessSquare piece, king = (gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing);
 
     p = fen;
 
@@ -18155,8 +18163,8 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize)
                     p++;
                 }
                 board[i][(j++)+gameInfo.holdingsWidth] = piece;
-                if(piece == WhiteKing) wKingRank = i;
-                if(piece == BlackKing) bKingRank = i;
+                if(piece == king) wKingRank = i;
+                if(piece == WHITE_TO_BLACK king) bKingRank = i;
            } else {
                return FALSE;
            }