From 8d643921e62f33b7e4f2bd9f224ae68ec87e203c Mon Sep 17 00:00:00 2001
From: H.G.Muller <hgm@hgm-xboard.(none)>
Date: Tue, 23 Sep 2014 21:53:55 +0200
Subject: [PATCH] Allow definition of castling in piece command

Castling is defined by the O atom, with a suffix indicating the number
of steps the King must step in the direction of the corner. Kings keep
their normal castling unless overruled by this. Can currently only be
used on the variant's royal piece, as XBoard's ApplyMove() is not smart
enough to understand displacing the corner piece is implied when it is
used on other pieces.
---
 moves.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/moves.c b/moves.c
index 9700dbf..e3afe36 100644
--- a/moves.c
+++ b/moves.c
@@ -256,6 +256,9 @@ MovesFromString (Board board, int flags, int f, int r, char *desc, MoveCallback
 	if(expo > 9) p++;                             // allow double-digit
 	desc = p;                                     // this is start of next move
 	if(initial && board[r][f] != initialPosition[r][f]) continue;
+	if(expo > 1 && dx == 0 && dy == 0) {          // castling indicated by O + number
+	    mode |= 16; dy = 1;
+	}
         do {
 	  for(dir=0, bit=1; dir<8; dir++, bit += bit) { // loop over directions
 	    int i = expo, vx, vy;
@@ -274,6 +277,15 @@ MovesFromString (Board board, int flags, int f, int r, char *desc, MoveCallback
 		if(mode & 8 && y == board[EP_RANK] && occup == 4 && board[EP_FILE] == x) { // to e.p. square
 		    cb(board, flags, mine == 1 ? WhiteCapturesEnPassant : BlackCapturesEnPassant, r, f, y, x, cl);
 		}
+		if(mode & 16) {              // castling
+		    i = 2;                   // kludge to elongate move indefinitely
+		    if(occup == 4) continue; // skip empty squares
+		    if(x == BOARD_LEFT   && board[y][x] == initialPosition[y][x]) // reached initial corner piece
+			cb(board, flags, mine == 1 ? WhiteQueenSideCastle : BlackQueenSideCastle, r, f, y, f - expo, cl);
+		    if(x == BOARD_RGHT-1 && board[y][x] == initialPosition[y][x])
+			cb(board, flags, mine == 1 ? WhiteKingSideCastle : BlackKingSideCastle, r, f, y, f + expo, cl);
+		    break;
+		}
 		if(occup & mode) cb(board, flags, NormalMove, r, f, y, x, cl); // allowed, generate
 		if(occup != 4) break; // not valid transit square
 	    } while(--i);
@@ -1218,6 +1230,7 @@ GenLegal (Board board, int  flags, MoveCallback callback, VOIDSTAR closure, Ches
     int ignoreCheck = (flags & F_IGNORE_CHECK) != 0;
     ChessSquare wKing = WhiteKing, bKing = BlackKing, *castlingRights = board[CASTLING];
     int inCheck = !ignoreCheck && CheckTest(board, flags, -1, -1, -1, -1, FALSE); // kludge alert: this would mark pre-existing checkers if status==1
+    char *p;
 
     cl.cb = callback;
     cl.cl = closure;
@@ -1232,6 +1245,9 @@ GenLegal (Board board, int  flags, MoveCallback callback, VOIDSTAR closure, Ches
         wKing = WhiteUnicorn; bKing = BlackUnicorn;
     }
 
+    p = (flags & F_WHITE_ON_MOVE ? pieceDesc[wKing] : pieceDesc[bKing]);
+    if(p && strchr(p, 'O')) return FALSE; // [HGM] gen: castlings were already generated from string
+
     for (ff = BOARD_WIDTH>>1; ff >= (BOARD_WIDTH-1)>>1; ff-- /*ics wild 1*/) {
 	if ((flags & F_WHITE_ON_MOVE) &&
 	    (flags & F_WHITE_KCASTLE_OK) &&
-- 
1.7.0.4