Automatically adapt board format to FEN
authorH.G. Muller <h.g.muller@hccnet.nl>
Sat, 7 Sep 2013 21:47:42 +0000 (23:47 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Sun, 22 Dec 2013 22:06:50 +0000 (23:06 +0100)
In some situations (such as loading a game or poition) the board-size
overrules are directly set to the values that can be deduced from the FEN.
The routine ParseFEN() has an extra parameter autoSize to control that.

backend.c
backend.h
gamelist.c
winboard/wclipbrd.c

index 6dae63d..4633377 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -8564,7 +8564,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
           if(*buf) SetCharTable(pieceToChar, buf); // do again, for it was spoiled by InitPosition
         }
       }
           if(*buf) SetCharTable(pieceToChar, buf); // do again, for it was spoiled by InitPosition
         }
       }
-      ParseFEN(boards[0], &dummy, message+s);
+      ParseFEN(boards[0], &dummy, message+s, FALSE);
       DrawPosition(TRUE, boards[0]);
       startedFromSetupPosition = TRUE;
       return;
       DrawPosition(TRUE, boards[0]);
       startedFromSetupPosition = TRUE;
       return;
@@ -8577,7 +8577,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
 
         GameEnds(GameUnfinished, "Engine aborts game", GE_XBOARD);
 
 
         GameEnds(GameUnfinished, "Engine aborts game", GE_XBOARD);
 
-        if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9)) {
+        if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9, FALSE)) {
             DisplayError(_("Bad FEN received from engine"), 0);
             return ;
         } else {
             DisplayError(_("Bad FEN received from engine"), 0);
             return ;
         } else {
@@ -12081,7 +12081,7 @@ GameContainsPosition (FILE *f, ListGame *lg)
        for(next = WhitePawn; next<EmptySquare; next++) keys[next] = random()>>8 ^ random()<<6 ^random()<<20;
        initDone = TRUE;
     }
        for(next = WhitePawn; next<EmptySquare; next++) keys[next] = random()>>8 ^ random()<<6 ^random()<<20;
        initDone = TRUE;
     }
-    if(lg->gameInfo.fen) ParseFEN(boards[scratch], &btm, lg->gameInfo.fen);
+    if(lg->gameInfo.fen) ParseFEN(boards[scratch], &btm, lg->gameInfo.fen, FALSE);
     else CopyBoard(boards[scratch], initialPosition); // default start position
     if(lg->moves) {
        turn = btm + 1;
     else CopyBoard(boards[scratch], initialPosition); // default start position
     if(lg->moves) {
        turn = btm + 1;
@@ -12403,7 +12403,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
        if (gameInfo.fen != NULL) {
          Board initial_position;
          startedFromSetupPosition = TRUE;
        if (gameInfo.fen != NULL) {
          Board initial_position;
          startedFromSetupPosition = TRUE;
-         if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen)) {
+         if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen, TRUE)) {
            Reset(TRUE, TRUE);
            DisplayError(_("Bad FEN position in file"), 0);
            return FALSE;
            Reset(TRUE, TRUE);
            DisplayError(_("Bad FEN position in file"), 0);
            return FALSE;
@@ -12740,7 +12740,7 @@ LoadPosition (FILE *f, int positionNumber, char *title)
     }
 
     if (fenMode) {
     }
 
     if (fenMode) {
-       if (!ParseFEN(initial_position, &blackPlaysFirst, line)) {
+       if (!ParseFEN(initial_position, &blackPlaysFirst, line, TRUE)) {
            DisplayError(_("Bad FEN position in file"), 0);
            return FALSE;
        }
            DisplayError(_("Bad FEN position in file"), 0);
            return FALSE;
        }
@@ -16518,7 +16518,7 @@ TypeInDoneEvent (char *move)
        ChessMove moveType;
 
        // [HGM] FENedit
        ChessMove moveType;
 
        // [HGM] FENedit
-       if(gameMode == EditPosition && ParseFEN(board, &n, move) ) {
+       if(gameMode == EditPosition && ParseFEN(board, &n, move, TRUE) ) {
                EditPositionPasteFEN(move);
                return;
        }
                EditPositionPasteFEN(move);
                return;
        }
@@ -17407,34 +17407,31 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts)
 }
 
 Boolean
 }
 
 Boolean
-ParseFEN (Board board, int *blackPlaysFirst, char *fen)
+ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize)
 {
 {
-    int i, j;
+    int i, j, k, w=0;
     char *p, c;
     int emptycount, virgin[BOARD_FILES];
     ChessSquare piece;
 
     p = fen;
 
     char *p, c;
     int emptycount, virgin[BOARD_FILES];
     ChessSquare piece;
 
     p = fen;
 
-    /* [HGM] by default clear Crazyhouse holdings, if present */
-    if(gameInfo.holdingsWidth) {
-       for(i=0; i<BOARD_HEIGHT; i++) {
-           board[i][0]             = EmptySquare; /* black holdings */
-           board[i][BOARD_WIDTH-1] = EmptySquare; /* white holdings */
-           board[i][1]             = (ChessSquare) 0; /* black counts */
-           board[i][BOARD_WIDTH-2] = (ChessSquare) 0; /* white counts */
-       }
-    }
-
     /* Piece placement data */
     for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
        j = 0;
        for (;;) {
     /* Piece placement data */
     for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
        j = 0;
        for (;;) {
-            if (*p == '/' || *p == ' ' || (*p == '[' && i == 0) ) {
-                if (*p == '/') p++;
+            if (*p == '/' || *p == ' ' || *p == '[' ) {
+               if(j > w) w = j;
                 emptycount = gameInfo.boardWidth - j;
                 while (emptycount--)
                         board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
                 emptycount = gameInfo.boardWidth - j;
                 while (emptycount--)
                         board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
+                if (*p == '/') p++;
+               else if(autoSize) { // we stumbled unexpectedly into end of board
+                    for(k=i; k<BOARD_HEIGHT; k++) { // too few ranks; shift towards bottom
+                       for(j=0; j<BOARD_WIDTH; j++) board[k-i][j] = board[k][j];
+                    }
+                   appData.NrRanks = gameInfo.boardHeight - i; i=0;
+                }
                break;
 #if(BOARD_FILES >= 10)
             } else if(*p=='x' || *p=='X') { /* [HGM] X means 10 */
                break;
 #if(BOARD_FILES >= 10)
             } else if(*p=='x' || *p=='X') { /* [HGM] X means 10 */
@@ -17474,6 +17471,18 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen)
     }
     while (*p == '/' || *p == ' ') p++;
 
     }
     while (*p == '/' || *p == ' ') p++;
 
+    if(autoSize) appData.NrFiles = w, InitPosition(TRUE);
+
+    /* [HGM] by default clear Crazyhouse holdings, if present */
+    if(gameInfo.holdingsWidth) {
+       for(i=0; i<BOARD_HEIGHT; i++) {
+           board[i][0]             = EmptySquare; /* black holdings */
+           board[i][BOARD_WIDTH-1] = EmptySquare; /* white holdings */
+           board[i][1]             = (ChessSquare) 0; /* black counts */
+           board[i][BOARD_WIDTH-2] = (ChessSquare) 0; /* white counts */
+       }
+    }
+
     /* [HGM] look for Crazyhouse holdings here */
     while(*p==' ') p++;
     if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {
     /* [HGM] look for Crazyhouse holdings here */
     while(*p==' ') p++;
     if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {
@@ -17667,7 +17676,7 @@ EditPositionPasteFEN (char *fen)
   if (fen != NULL) {
     Board initial_position;
 
   if (fen != NULL) {
     Board initial_position;
 
-    if (!ParseFEN(initial_position, &blackPlaysFirst, fen)) {
+    if (!ParseFEN(initial_position, &blackPlaysFirst, fen, TRUE)) {
       DisplayError(_("Bad FEN position in clipboard"), 0);
       return ;
     } else {
       DisplayError(_("Bad FEN position in clipboard"), 0);
       return ;
     } else {
index c82c989..69197ce 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -243,7 +243,7 @@ Boolean DisplayBook P((int moveNr));
 void SaveToBook P((char *text));
 void HoverEvent P((int hiX, int hiY, int x, int y));
 int PackGame P((Board board));
 void SaveToBook P((char *text));
 void HoverEvent P((int hiX, int hiY, int x, int y));
 int PackGame P((Board board));
-Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));
+Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen, Boolean autoSize));
 void ApplyMove P((int fromX, int fromY, int toX, int toY, int promoChar, Board board));
 void PackMove P((int fromX, int fromY, int toX, int toY, ChessSquare promoPiece));
 void ics_printf P((char *format, ...));
 void ApplyMove P((int fromX, int fromY, int toX, int toY, int promoChar, Board board));
 void PackMove P((int fromX, int fromY, int toX, int toY, ChessSquare promoPiece));
 void ics_printf P((char *format, ...));
index 0c2f1b6..a96aeca 100644 (file)
@@ -305,7 +305,7 @@ GameListBuild (FILE *f)
            } while (cm == PGNTag || cm == Comment);
            if(1) {
                int btm=0;
            } while (cm == PGNTag || cm == Comment);
            if(1) {
                int btm=0;
-               if(currentListGame->gameInfo.fen) ParseFEN(boards[scratch], &btm, currentListGame->gameInfo.fen);
+               if(currentListGame->gameInfo.fen) ParseFEN(boards[scratch], &btm, currentListGame->gameInfo.fen, FALSE);
                else CopyBoard(boards[scratch], initialPosition);
                plyNr = (btm != 0);
                currentListGame->moves = PackGame(boards[scratch]);
                else CopyBoard(boards[scratch], initialPosition);
                plyNr = (btm != 0);
                currentListGame->moves = PackGame(boards[scratch]);
index d1c5538..08a97bf 100644 (file)
@@ -42,7 +42,6 @@
 \r
 /* Imports from winboard.c */\r
 extern HWND hwndMain;\r
 \r
 /* Imports from winboard.c */\r
 extern HWND hwndMain;\r
-Boolean ParseFEN(Board b, int *stm, char *FEN);\r
 \r
 /* File globals */\r
 static char *copyTemp;\r
 \r
 /* File globals */\r
 static char *copyTemp;\r
@@ -305,7 +304,7 @@ VOID PasteGameOrFENFromClipboard()
   }\r
 \r
   // [HGM] paste any: make still smarter, to allow pasting of games without tags, recognize FEN in stead\r
   }\r
 \r
   // [HGM] paste any: make still smarter, to allow pasting of games without tags, recognize FEN in stead\r
-  if(!ParseFEN(dummyBoard, &dummy, buf) ) {\r
+  if(!ParseFEN(dummyBoard, &dummy, buf, 0) ) {\r
       PasteGameFromString( buf );\r
   }\r
   else {\r
       PasteGameFromString( buf );\r
   }\r
   else {\r