Integrate castling and e.p. rights into board array; bugfix for EditPosition
authorH.G. Muller <h.g.muller@hccnet.nl>
Fri, 6 Nov 2009 03:23:44 +0000 (19:23 -0800)
committerArun Persaud <arun@nubati.net>
Fri, 6 Nov 2009 06:44:15 +0000 (22:44 -0800)
A large-scale operation that I have been postponing since the very first 4.4.0:
The castling and e.p. rights are now integrated into the board array, as
boards[moveNr][CASTLING][i] replacing castlingRights[moveNr][i] and
boards[moveNr][EP_STATUS] replacing epStatus[moveNr]
These quantities are now automatically copied with the position by CopyBoards
(allowing the removal of lots of dedicated copying code), and passed as
function arguments with the position (so that the moves.c functions like
TestLegality, MateTest, CoordsToAlgebraic, Disambiguate, GenLegal
no longer need explicit e.p. and castling parameters.

Also fixed a bug introduced by a recent previous fix: by adding fake castling
rights to a position set up through the EditPosition menu, I destroyed the
castling rights of a pasted FEN. Faking castling rights is now made conditional
in EditPositionDone(), depending on the caller. (I had not realized it was also
called after FEN pasting, to send the position to the engine.)

backend.c
book.c
common.h
moves.c
moves.h
parser.h
parser.l
winboard/jaws.c
winboard/winboard.c
xboard.c

index 0a51282..7f8db9e 100755 (executable)
--- a/backend.c
+++ b/backend.c
@@ -160,7 +160,7 @@ int LoadGameFromFile P((char *filename, int n, char *title, int useList));
 int LoadPositionFromFile P((char *filename, int n, char *title));
 int SavePositionToFile P((char *filename));
 void ApplyMove P((int fromX, int fromY, int toX, int toY, int promoChar,
-                 Board board, char *castle, char *ep));
+                                                                               Board board));
 void MakeMove P((int fromX, int fromY, int toX, int toY, int promoChar));
 void ShowMove P((int fromX, int fromY, int toX, int toY));
 int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
@@ -168,7 +168,7 @@ int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
 void BackwardInner P((int target));
 void ForwardInner P((int target));
 void GameEnds P((ChessMove result, char *resultDetails, int whosays));
-void EditPositionDone P((void));
+void EditPositionDone P((Boolean fakeRights));
 void PrintOpponents P((FILE *fp));
 void PrintPosition P((FILE *fp, int move));
 void StartChessProgram P((ChessProgramState *cps));
@@ -441,47 +441,44 @@ AppData appData;
 
 Board boards[MAX_MOVES];
 /* [HGM] Following 7 needed for accurate legality tests: */
-signed char  epStatus[MAX_MOVES];
-signed char  castlingRights[MAX_MOVES][BOARD_SIZE]; // stores files for pieces with castling rights or -1
-signed char  castlingRank[BOARD_SIZE]; // and corresponding ranks
-signed char  initialRights[BOARD_SIZE], FENcastlingRights[BOARD_SIZE], fileRights[BOARD_SIZE];
+signed char  castlingRank[BOARD_FILES]; // and corresponding ranks
+signed char  initialRights[BOARD_FILES];
 int   nrCastlingRights; // For TwoKings, or to implement castling-unknown status
 int   initialRulePlies, FENrulePlies;
-char  FENepStatus;
 FILE  *serverMoves = NULL; // next two for broadcasting (/serverMoves option)
 int loadFlag = 0; 
 int shuffleOpenings;
 int mute; // mute all sounds
 
-ChessSquare  FIDEArray[2][BOARD_SIZE] = {
+ChessSquare  FIDEArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
        WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackBishop, BlackQueen,
        BlackKing, BlackBishop, BlackKnight, BlackRook }
 };
 
-ChessSquare twoKingsArray[2][BOARD_SIZE] = {
+ChessSquare twoKingsArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
        WhiteKing, WhiteKing, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackBishop, BlackQueen,
         BlackKing, BlackKing, BlackKnight, BlackRook }
 };
 
-ChessSquare  KnightmateArray[2][BOARD_SIZE] = {
+ChessSquare  KnightmateArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteMan, WhiteBishop, WhiteQueen,
         WhiteUnicorn, WhiteBishop, WhiteMan, WhiteRook },
     { BlackRook, BlackMan, BlackBishop, BlackQueen,
         BlackUnicorn, BlackBishop, BlackMan, BlackRook }
 };
 
-ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] Queen side differs from King side */
+ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */
     { WhiteCannon, WhiteNightrider, WhiteAlfil, WhiteQueen,
         WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
     { BlackCannon, BlackNightrider, BlackAlfil, BlackQueen,
        BlackKing, BlackBishop, BlackKnight, BlackRook }
 };
 
-ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */
+ChessSquare ShatranjArray[2][BOARD_FILES] = { /* [HGM] (movGen knows about Shatranj Q and P) */
     { WhiteRook, WhiteKnight, WhiteAlfil, WhiteKing,
         WhiteFerz, WhiteAlfil, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackAlfil, BlackKing,
@@ -489,36 +486,36 @@ ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatra
 };
 
 
-#if (BOARD_SIZE>=10)
-ChessSquare ShogiArray[2][BOARD_SIZE] = {
+#if (BOARD_FILES>=10)
+ChessSquare ShogiArray[2][BOARD_FILES] = {
     { WhiteQueen, WhiteKnight, WhiteFerz, WhiteWazir,
         WhiteKing, WhiteWazir, WhiteFerz, WhiteKnight, WhiteQueen },
     { BlackQueen, BlackKnight, BlackFerz, BlackWazir,
         BlackKing, BlackWazir, BlackFerz, BlackKnight, BlackQueen }
 };
 
-ChessSquare XiangqiArray[2][BOARD_SIZE] = {
+ChessSquare XiangqiArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteAlfil, WhiteFerz,
         WhiteWazir, WhiteFerz, WhiteAlfil, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackAlfil, BlackFerz,
         BlackWazir, BlackFerz, BlackAlfil, BlackKnight, BlackRook }
 };
 
-ChessSquare CapablancaArray[2][BOARD_SIZE] = {
+ChessSquare CapablancaArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteAngel, WhiteBishop, WhiteQueen, 
         WhiteKing, WhiteBishop, WhiteMarshall, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackAngel, BlackBishop, BlackQueen, 
         BlackKing, BlackBishop, BlackMarshall, BlackKnight, BlackRook }
 };
 
-ChessSquare GreatArray[2][BOARD_SIZE] = {
+ChessSquare GreatArray[2][BOARD_FILES] = {
     { WhiteDragon, WhiteKnight, WhiteAlfil, WhiteGrasshopper, WhiteKing, 
         WhiteSilver, WhiteCardinal, WhiteAlfil, WhiteKnight, WhiteDragon },
     { BlackDragon, BlackKnight, BlackAlfil, BlackGrasshopper, BlackKing, 
         BlackSilver, BlackCardinal, BlackAlfil, BlackKnight, BlackDragon },
 };
 
-ChessSquare JanusArray[2][BOARD_SIZE] = {
+ChessSquare JanusArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteAngel, WhiteKnight, WhiteBishop, WhiteKing, 
         WhiteQueen, WhiteBishop, WhiteKnight, WhiteAngel, WhiteRook },
     { BlackRook, BlackAngel, BlackKnight, BlackBishop, BlackKing, 
@@ -526,7 +523,7 @@ ChessSquare JanusArray[2][BOARD_SIZE] = {
 };
 
 #ifdef GOTHIC
-ChessSquare GothicArray[2][BOARD_SIZE] = {
+ChessSquare GothicArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall, 
         WhiteKing, WhiteAngel, WhiteBishop, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackMarshall, 
@@ -537,7 +534,7 @@ ChessSquare GothicArray[2][BOARD_SIZE] = {
 #endif // !GOTHIC
 
 #ifdef FALCON
-ChessSquare FalconArray[2][BOARD_SIZE] = {
+ChessSquare FalconArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteLance, WhiteQueen, 
         WhiteKing, WhiteLance, WhiteBishop, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackBishop, BlackLance, BlackQueen, 
@@ -547,23 +544,23 @@ ChessSquare FalconArray[2][BOARD_SIZE] = {
 #define FalconArray CapablancaArray
 #endif // !FALCON
 
-#else // !(BOARD_SIZE>=10)
+#else // !(BOARD_FILES>=10)
 #define XiangqiPosition FIDEArray
 #define CapablancaArray FIDEArray
 #define GothicArray FIDEArray
 #define GreatArray FIDEArray
-#endif // !(BOARD_SIZE>=10)
+#endif // !(BOARD_FILES>=10)
 
-#if (BOARD_SIZE>=12)
-ChessSquare CourierArray[2][BOARD_SIZE] = {
+#if (BOARD_FILES>=12)
+ChessSquare CourierArray[2][BOARD_FILES] = {
     { WhiteRook, WhiteKnight, WhiteAlfil, WhiteBishop, WhiteMan, WhiteKing,
         WhiteFerz, WhiteWazir, WhiteBishop, WhiteAlfil, WhiteKnight, WhiteRook },
     { BlackRook, BlackKnight, BlackAlfil, BlackBishop, BlackMan, BlackKing,
         BlackFerz, BlackWazir, BlackBishop, BlackAlfil, BlackKnight, BlackRook }
 };
-#else // !(BOARD_SIZE>=12)
+#else // !(BOARD_FILES>=12)
 #define CourierArray CapablancaArray
-#endif // !(BOARD_SIZE>=12)
+#endif // !(BOARD_FILES>=12)
 
 
 Board initialPosition;
@@ -646,8 +643,8 @@ InitBackEnd1()
 
         for( i=0; i<MAX_MOVES; i++ ) {
             pvInfoList[i].depth = -1;
-            epStatus[i]=EP_NONE;
-            for( j=0; j<BOARD_SIZE; j++ ) castlingRights[i][j] = -1;
+            boards[i][EP_STATUS] = EP_NONE;
+            for( j=0; j<BOARD_FILES-2; j++ ) boards[i][CASTLING][j] = NoRights;
         }
     }
 
@@ -1193,10 +1190,9 @@ InitBackEnd3 P((void))
             }
             /* [HGM] loadPos: make that every new game uses the setup */
             /* from file as long as we do not switch variant          */
-            if(!blackPlaysFirst) { int i;
+            if(!blackPlaysFirst) {
                 startedFromPositionFile = TRUE;
                 CopyBoard(filePosition, boards[0]);
-                for(i=0; i<BOARD_SIZE; i++) fileRights[i] = castlingRights[0][i];
             }
        }
        if (initialMode == AnalyzeMode) {
@@ -1905,7 +1901,7 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
     ChessSquare piece;
 
     if(gameInfo.holdingsWidth < 2)  return;
-    if(gameInfo.variant != VariantBughouse && board[BOARD_SIZE-1][BOARD_SIZE-2])
+    if(gameInfo.variant != VariantBughouse && board[HOLDINGS_SET])
        return; // prevent overwriting by pre-board holdings
 
     if( (int)lowestPiece >= BlackPawn ) {
@@ -2082,7 +2078,8 @@ read_from_ics(isr, closure, data, count, error)
 
     if (appData.debugMode) { int f = forwardMostMove;
         fprintf(debugFP, "ics input %d, castling = %d %d %d %d %d %d\n", f,
-                castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);
+                boards[f][CASTLING][0],boards[f][CASTLING][1],boards[f][CASTLING][2],
+                boards[f][CASTLING][3],boards[f][CASTLING][4],boards[f][CASTLING][5]);
     }
     if (count > 0) {
        /* If last read ended with a partial line that we couldn't parse,
@@ -3307,7 +3304,7 @@ read_from_ics(isr, closure, data, count, error)
                         /* [HGM] copy holdings to board holdings area */
                         CopyHoldings(boards[forwardMostMove], white_holding, WhitePawn);
                         CopyHoldings(boards[forwardMostMove], black_holding, BlackPawn);
-                        boards[forwardMostMove][BOARD_SIZE-1][BOARD_SIZE-2] = 1; // flag holdings as set
+                        boards[forwardMostMove][HOLDINGS_SET] = 1; // flag holdings as set
 #if ZIPPY
                        if (appData.zippyPlay && first.initDone) {
                            ZippyHoldings(white_holding, black_holding,
@@ -3660,7 +3657,7 @@ ParseBoard12(string)
       }
     }
     CopyBoard(boards[moveNum], board);
-    boards[moveNum][BOARD_SIZE-1][BOARD_SIZE-2] = 0; // [HGM] indicate holdings not set
+    boards[moveNum][HOLDINGS_SET] = 0; // [HGM] indicate holdings not set
     if (moveNum == 0) {
        startedFromSetupPosition =
          !CompareBoards(board, initialPosition);
@@ -3683,38 +3680,38 @@ ParseBoard12(string)
 
         for(i=BOARD_LEFT, j= -1; i<BOARD_RGHT; i++)
             if(board[0][i] == WhiteRook) j = i;
-        initialRights[0] = castlingRights[moveNum][0] = (castle_ws == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);
+        initialRights[0] = boards[moveNum][CASTLING][0] = (castle_ws == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
         for(i=BOARD_RGHT-1, j= -1; i>=BOARD_LEFT; i--)
             if(board[0][i] == WhiteRook) j = i;
-        initialRights[1] = castlingRights[moveNum][1] = (castle_wl == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);
+        initialRights[1] = boards[moveNum][CASTLING][1] = (castle_wl == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
         for(i=BOARD_LEFT, j= -1; i<BOARD_RGHT; i++)
             if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;
-        initialRights[3] = castlingRights[moveNum][3] = (castle_bs == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);
+        initialRights[3] = boards[moveNum][CASTLING][3] = (castle_bs == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
         for(i=BOARD_RGHT-1, j= -1; i>=BOARD_LEFT; i--)
             if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;
-        initialRights[4] = castlingRights[moveNum][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);
+        initialRights[4] = boards[moveNum][CASTLING][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
 
        if(gameInfo.variant == VariantKnightmate) { wKing = WhiteUnicorn; bKing = BlackUnicorn; }
         for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
-            if(board[0][k] == wKing) initialRights[2] = castlingRights[moveNum][2] = k;
+            if(board[0][k] == wKing) initialRights[2] = boards[moveNum][CASTLING][2] = k;
         for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
             if(board[BOARD_HEIGHT-1][k] == bKing)
-                initialRights[5] = castlingRights[moveNum][5] = k;
+                initialRights[5] = boards[moveNum][CASTLING][5] = k;
     } else { int r;
-        r = castlingRights[moveNum][0] = initialRights[0];
-        if(board[0][r] != WhiteRook) castlingRights[moveNum][0] = -1;
-        r = castlingRights[moveNum][1] = initialRights[1];
-        if(board[0][r] != WhiteRook) castlingRights[moveNum][1] = -1;
-        r = castlingRights[moveNum][3] = initialRights[3];
-        if(board[BOARD_HEIGHT-1][r] != BlackRook) castlingRights[moveNum][3] = -1;
-        r = castlingRights[moveNum][4] = initialRights[4];
-        if(board[BOARD_HEIGHT-1][r] != BlackRook) castlingRights[moveNum][4] = -1;
+        r = boards[moveNum][CASTLING][0] = initialRights[0];
+        if(board[0][r] != WhiteRook) boards[moveNum][CASTLING][0] = NoRights;
+        r = boards[moveNum][CASTLING][1] = initialRights[1];
+        if(board[0][r] != WhiteRook) boards[moveNum][CASTLING][1] = NoRights;
+        r = boards[moveNum][CASTLING][3] = initialRights[3];
+        if(board[BOARD_HEIGHT-1][r] != BlackRook) boards[moveNum][CASTLING][3] = NoRights;
+        r = boards[moveNum][CASTLING][4] = initialRights[4];
+        if(board[BOARD_HEIGHT-1][r] != BlackRook) boards[moveNum][CASTLING][4] = NoRights;
         /* wildcastle kludge: always assume King has rights */
-        r = castlingRights[moveNum][2] = initialRights[2];
-        r = castlingRights[moveNum][5] = initialRights[5];
+        r = boards[moveNum][CASTLING][2] = initialRights[2];
+        r = boards[moveNum][CASTLING][5] = initialRights[5];
     }
     /* [HGM] e.p. rights. Assume that ICS sends file number here? */
-    epStatus[moveNum] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;
+    boards[moveNum][EP_STATUS] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;
 
     
     if (ics_getting_history == H_GOT_REQ_HEADER ||
@@ -3804,7 +3801,8 @@ ParseBoard12(string)
   if (appData.debugMode) {
     if (appData.debugMode) { int f = forwardMostMove;
         fprintf(debugFP, "parseboard %d, castling = %d %d %d %d %d %d\n", f,
-                castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);
+                boards[f][CASTLING][0],boards[f][CASTLING][1],boards[f][CASTLING][2],
+                boards[f][CASTLING][3],boards[f][CASTLING][4],boards[f][CASTLING][5]);
     }
     fprintf(debugFP, "accepted move %s from ICS, parse it.\n", move_str);
     fprintf(debugFP, "moveNum = %d\n", moveNum);
@@ -3850,11 +3848,10 @@ ParseBoard12(string)
          // end of long SAN patch
          if (valid) {
            (void) CoordsToAlgebraic(boards[moveNum - 1],
-                                    PosFlags(moveNum - 1), EP_UNKNOWN,
+                                    PosFlags(moveNum - 1),
                                     fromY, fromX, toY, toX, promoChar,
                                     parseList[moveNum-1]);
-            switch (MateTest(boards[moveNum], PosFlags(moveNum), EP_UNKNOWN,
-                             castlingRights[moveNum]) ) {
+            switch (MateTest(boards[moveNum], PosFlags(moveNum)) ) {
              case MT_NONE:
              case MT_STALEMATE:
              default:
@@ -4507,12 +4504,12 @@ void SetUpShuffle(Board board, int number)
            // Last King gets castling rights
            while(piecesLeft[(int)WhiteUnicorn]) {
                i = put(board, WhiteUnicorn, 0, piecesLeft[(int)WhiteRook]/2, ANY);
-               initialRights[2]  = initialRights[5]  = castlingRights[0][2] = castlingRights[0][5] = i;
+               initialRights[2]  = initialRights[5]  = boards[0][CASTLING][2] = boards[0][CASTLING][5] = i;
            }
 
            while(piecesLeft[(int)WhiteKing]) {
                i = put(board, WhiteKing, 0, piecesLeft[(int)WhiteRook]/2, ANY);
-               initialRights[2]  = initialRights[5]  = castlingRights[0][2] = castlingRights[0][5] = i;
+               initialRights[2]  = initialRights[5]  = boards[0][CASTLING][2] = boards[0][CASTLING][5] = i;
            }
 
 
@@ -4527,9 +4524,9 @@ void SetUpShuffle(Board board, int number)
                if(PosFlags(0) & F_FRC_TYPE_CASTLING) { // first and last Rook get FRC castling rights
                        if(first) {
                                first=0;
-                               initialRights[1]  = initialRights[4]  = castlingRights[0][1] = castlingRights[0][4] = i;
+                               initialRights[1]  = initialRights[4]  = boards[0][CASTLING][1] = boards[0][CASTLING][4] = i;
                        }
-                       initialRights[0]  = initialRights[3]  = castlingRights[0][0] = castlingRights[0][3] = i;
+                       initialRights[0]  = initialRights[3]  = boards[0][CASTLING][0] = boards[0][CASTLING][3] = i;
                }
        }
        for(i=BOARD_LEFT; i<BOARD_RGHT; i++) { // copy black from white
@@ -4603,7 +4600,7 @@ void
 InitPosition(redraw)
      int redraw;
 {
-    ChessSquare (* pieces)[BOARD_SIZE];
+    ChessSquare (* pieces)[BOARD_FILES];
     int i, j, pawnRow, overrule,
     oldx = gameInfo.boardWidth,
     oldy = gameInfo.boardHeight,