Castle with nearest rather than corner piece
[xboard.git] / backend.c
index 42f2ac2..670eb4b 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5501,7 +5501,6 @@ char yy_textstr[8000];
 Boolean
 ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fromY, int *toX, int *toY, char *promoChar)
 {
-    int badFrom;
     *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
 
     switch (*moveType) {
@@ -5528,14 +5527,13 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
       case BlackASideCastleFR:
       /* End of code added by Tord */
       case IllegalMove:                /* bug or odd chess variant */
+       if(currentMoveString[1] == '@') goto drop; // illegal drop
         *fromX = currentMoveString[0] - AAA;
         *fromY = currentMoveString[1] - ONE;
         *toX = currentMoveString[2] - AAA;
         *toY = currentMoveString[3] - ONE;
        *promoChar = currentMoveString[4];
-       badFrom = (*fromX < BOARD_LEFT || *fromX >= BOARD_RGHT || *fromY < 0 || *fromY >= BOARD_HEIGHT);
-       if(currentMoveString[1] == '@') { badFrom = FALSE; *fromX = CharToPiece(currentMoveString[0]); *fromY = DROP_RANK; } // illegal drop
-        if (badFrom ||
+        if (*fromX < BOARD_LEFT || *fromX >= BOARD_RGHT || *fromY < 0 || *fromY >= BOARD_HEIGHT ||
             *toX < BOARD_LEFT || *toX >= BOARD_RGHT || *toY < 0 || *toY >= BOARD_HEIGHT) {
     if (appData.debugMode) {
         fprintf(debugFP, "Off-board move (%d,%d)-(%d,%d)%c, type = %d\n", *fromX, *fromY, *toX, *toY, *promoChar, *moveType);
@@ -5553,6 +5551,7 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
 
       case WhiteDrop:
       case BlackDrop:
+      drop:
        *fromX = *moveType == WhiteDrop ?
          (int) CharToPiece(ToUpper(currentMoveString[0])) :
          (int) CharToPiece(ToLower(currentMoveString[0]));
@@ -8668,12 +8667,13 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            safeStrCpy(firstLeg, machineMove, 20); // just remember it for processing when second leg arrives
            return;
        } else if(firstLeg[0]) { // there was a previous leg;
-           // only support case where same piece makes two step (and don't even test that!)
+           // only support case where same piece makes two step
            char buf[20], *p = machineMove+1, *q = buf+1, f;
            safeStrCpy(buf, machineMove, 20);
            while(isdigit(*q)) q++; // find start of to-square
            safeStrCpy(machineMove, firstLeg, 20);
-           while(isdigit(*p)) p++;
+           while(isdigit(*p)) p++; // to-square of first leg (which is now copied to machineMove)
+           if(*p == *buf)          // if first-leg to not equal to second-leg from first leg says unmodified (assume it ia King move of castling)
            safeStrCpy(p, q, 20); // glue to-square of second leg to from-square of first, to process over-all move
            sscanf(buf, "%c%d", &f, &killY); killX = f - AAA; killY -= ONE - '0'; // pass intermediate square to MakeMove in global
            firstLeg[0] = NULLCHAR;
@@ -10011,8 +10011,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
      if(gameInfo.variant == VariantKnightmate)
          king += (int) WhiteUnicorn - (int) WhiteKing;
 
-    if(piece != WhiteKing && piece != BlackKing && pieceDesc[piece] && killX >= 0 && strchr(pieceDesc[piece], 'O') // Betza castling-enabled
-       && (piece < BlackPawn ? killed < BlackPawn : killed >= BlackPawn)) {    // and captures own
+    if(pieceDesc[piece] && killX >= 0 && strchr(pieceDesc[piece], 'O') // Betza castling-enabled
+       && (piece < BlackPawn ? killed < BlackPawn : killed >= BlackPawn)) {    // and tramples own
        board[toY][toX] = piece; board[fromY][fromX] = EmptySquare;
        board[toY][toX + (killX < fromX ? 1 : -1)] = killed;
         board[EP_STATUS] = EP_NONE; // capture was fake!
@@ -10044,19 +10044,19 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
     } else if (board[fromY][fromX] == king
         && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
         && toY == fromY && toX > fromX+1) {
+       for(rookX=fromX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT-1; rookX++); // castle with nearest piece
+        board[fromY][toX-1] = board[fromY][rookX];
+        board[fromY][rookX] = EmptySquare;
        board[fromY][fromX] = EmptySquare;
         board[toY][toX] = king;
-       for(rookX=BOARD_RGHT-1; board[toY][rookX] == DarkSquare && rookX > toX + 1; rookX--);
-        board[toY][toX-1] = board[fromY][rookX];
-        board[fromY][rookX] = EmptySquare;
     } else if (board[fromY][fromX] == king
         && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
                && toY == fromY && toX < fromX-1) {
+       for(rookX=fromX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--); // castle with nearest piece
+        board[fromY][toX+1] = board[fromY][rookX];
+        board[fromY][rookX] = EmptySquare;
        board[fromY][fromX] = EmptySquare;
         board[toY][toX] = king;
-       for(rookX=BOARD_LEFT; board[toY][rookX] == DarkSquare && rookX < toX - 1; rookX++);
-        board[toY][toX+1] = board[fromY][rookX];
-        board[fromY][rookX] = EmptySquare;
     } else if ((board[fromY][fromX] == WhitePawn && gameInfo.variant != VariantXiangqi ||
                 board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu)
                && toY >= BOARD_HEIGHT-promoRank && promoChar // defaulting to Q is done elsewhere
@@ -10095,19 +10095,19 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
     } else if (board[fromY][fromX] == king
         && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
                && toY == fromY && toX > fromX+1) {
+       for(rookX=toX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT - 1; rookX++);
+        board[fromY][toX-1] = board[fromY][rookX];
+        board[fromY][rookX] = EmptySquare;
        board[fromY][fromX] = EmptySquare;
         board[toY][toX] = king;
-       for(rookX=BOARD_RGHT-1; board[toY][rookX] == DarkSquare && rookX > toX + 1; rookX--);
-        board[toY][toX-1] = board[fromY][rookX];
-        board[fromY][rookX] = EmptySquare;
     } else if (board[fromY][fromX] == king
         && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
                && toY == fromY && toX < fromX-1) {
+       for(rookX=toX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--);
+        board[fromY][toX+1] = board[fromY][rookX];
+        board[fromY][rookX] = EmptySquare;
        board[fromY][fromX] = EmptySquare;
         board[toY][toX] = king;
-       for(rookX=BOARD_LEFT; board[toY][rookX] == DarkSquare && rookX < toX - 1; rookX++);
-        board[toY][toX+1] = board[fromY][rookX];
-        board[fromY][rookX] = EmptySquare;
     } else if (fromY == 7 && fromX == 3
               && board[fromY][fromX] == BlackKing
               && toY == 7 && toX == 5) {