Implement non-royal castling
authorH.G.Muller <hgm@hgm-xboard.(none)>
Sun, 2 Nov 2014 14:31:34 +0000 (15:31 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Thu, 7 May 2015 18:53:31 +0000 (20:53 +0200)
The Betza move generator allows castlings to be specified on non-royal
pieces, and indeed the Omega-Chess 'guarding' castles Q with R. To
prevent ambiguity this is implemented as a two-leg move QxR-s (with 's'
the target square specified in the O atom). This automatically takes care
of removal of the 'Rook', so that in ApplyMove() we only have to put it
back on the proper side of the 'King'.

backend.c
moves.c

index 3e432ae..dd8bbb1 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -7501,6 +7501,7 @@ LeftClick (ClickType clickType, int xPix, int yPix)
        toP = boards[currentMove][y][x];
        frc = appData.fischerCastling || gameInfo.variant == VariantSChess;
        if( (killX < 0 || x != fromX || y != fromY) && // [HGM] lion: do not interpret igui as deselect!
+           legal[y][x] == 0 && // if engine told we can move to here, do it even if own piece
           ((WhitePawn <= fromP && fromP <= WhiteKing &&
             WhitePawn <= toP && toP <= WhiteKing &&
             !(fromP == WhiteKing && toP == WhiteRook && frc) &&
@@ -9889,7 +9890,7 @@ ParseGameHistory (char *game)
 void
 ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
 {
-  ChessSquare captured = board[toY][toX], piece, king; int p, rookX, oldEP = EP_NONE, berolina = 0;
+  ChessSquare captured = board[toY][toX], piece, king, killed; int p, rookX, oldEP = EP_NONE, berolina = 0;
   int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1;
 
     /* [HGM] compute & store e.p. status and castling rights for new position */
@@ -9913,6 +9914,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
 
       if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something
 //           victim = board[killY][killX],
+           killed = board[killY][killX],
            board[killY][killX] = EmptySquare,
            board[EP_STATUS] = EP_CAPTURE;
 
@@ -9984,6 +9986,12 @@ 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
+       board[toY][toX] = piece; board[fromY][fromX] = EmptySquare;
+       board[toY][toX + (killX < fromX ? 1 : -1)] = killed;
+        board[EP_STATUS] = EP_NONE; // capture was fake!
+    } else
     /* Code added by Tord: */
     /* FRC castling assumed when king captures friendly rook. [HGM] or RxK for S-Chess */
     if (board[fromY][fromX] == WhiteKing && board[toY][toX] == WhiteRook ||
diff --git a/moves.c b/moves.c
index b4edc45..dbc8f41 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -433,10 +433,20 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle
                if(mode & 1024) {            // castling
                    i = 2;                   // kludge to elongate move indefinitely
                    if(occup == 4) continue; // skip empty squares
-                   if((x == BOARD_LEFT || vx < 0 && board[y][x-1] == DarkSquare)  && board[y][x] == initialPosition[y][x]) // reached initial corner piece
+                   if((x == BOARD_LEFT || vx < 0 && board[y][x-1] == DarkSquare)  && board[y][x] == initialPosition[y][x]) { // reached initial corner piece
+                     if(pc != WhiteKing && pc != BlackKing) { // non-royal castling (to be entered as two-leg move via 'Rook')
+                       if(killX < 0) cb(board, flags, FirstLeg,   r, f, y, x, cl);
+                       legNr <<= 1;  cb(board, flags, NormalMove, r, f, y, f - expo, cl); legNr >>= 1;
+                     } else
                        cb(board, flags, mine == 1 ? WhiteQueenSideCastle : BlackQueenSideCastle, r, f, y, f - expo, cl);
-                   if((x == BOARD_RGHT-1 || vx > 0 && board[y][x+1] == DarkSquare) && board[y][x] == initialPosition[y][x])
+                   }
+                   if((x == BOARD_RGHT-1 || vx > 0 && board[y][x+1] == DarkSquare) && board[y][x] == initialPosition[y][x]) {
+                     if(pc != WhiteKing && pc != BlackKing) {
+                       if(killX < 0) cb(board, flags, FirstLeg,   r, f, y, x, cl);
+                       legNr <<= 1;  cb(board, flags, NormalMove, r, f, y, f + expo, cl); legNr >>= 1;
+                     } else
                        cb(board, flags, mine == 1 ? WhiteKingSideCastle : BlackKingSideCastle, r, f, y, f + expo, cl);
+                   }
                    break;
                }
                if(mode & 16 && (board[y][x] == WhiteKing || board[y][x] == BlackKing)) break; // tame piece, cannot capture royal