From: H.G.Muller Date: Sun, 31 May 2020 11:13:13 +0000 (+0200) Subject: Implement XBetza unload modifier X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=5be6b2258152344d71fe7a457642c65735bebf87;p=xboard.git Implement XBetza unload modifier Move legs containing a 'u' modifier will cause a piece captured or destroyed by the entire move to reappear on the starting square of that leg. This allows specification of swappers and pieces that push other pieces elsewhere. The encoding of the corresponding moves uses the same format as that for locust capture, and ApplyMove() distinguishes those from the occupation of the specified 'kill square'. For now this can only be used in a move without other (true) locust capture. Notation (SAN), and reading back of such moves is still unsolved. --- diff --git a/backend.c b/backend.c index b15b157..a370e7b 100644 --- a/backend.c +++ b/backend.c @@ -7302,6 +7302,7 @@ UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar) } } + if(moveType == Swap && killX < 0) killX = fromX, killY = fromY, moveType = NormalMove; FinishMove(moveType, fromX, fromY, toX, toY, promoChar); } @@ -7541,11 +7542,12 @@ Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VO typedef char Markers[BOARD_RANKS][BOARD_FILES]; Markers *m = (Markers *) closure; if(rf == fromY && ff == fromX && (killX < 0 ? !(rt == rf && ft == ff) && legNr & 1 : - kill2X < 0 ? rt == killY && ft == killX || legNr & 2 : rt == killY && ft == killX || legNr & 4)) + kill2X < 0 ? rt == killY && ft == killX || legNr & 2 : rt == killY && ft == killX || legNr & 4)) { (*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare || kind == WhiteCapturesEnPassant - || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && (killX < 0 & legNr || legNr & 2 && kill2X < 0)), legal[rt][ft] = 3; - else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 3; + || kind == BlackCapturesEnPassant), legal[rt][ft] = 3; + if(kind == FirstLeg && (killX < 0 & legNr || legNr & 2 && kill2X < 0)) (*m)[rt][ft] = 5; + } else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 3; } static int hoverSavedValid; @@ -10509,6 +10511,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) board[EP_STATUS] = EP_CAPTURE; if( kill2X >= 0 && kill2Y >= 0) killed2 = board[kill2Y][kill2X], board[kill2Y][kill2X] = EmptySquare; + if(killed == EmptySquare) // [HGM] unload: kill-square also used for push destination + board[killY][killX] = board[toY][toX], board[EP_STATUS] = EP_NONE; } if( board[toY][toX] != EmptySquare ) { diff --git a/common.h b/common.h index 55daf29..5755e33 100644 --- a/common.h +++ b/common.h @@ -348,7 +348,7 @@ typedef enum { WhitePromotion, WhiteNonPromotion, BlackPromotion, BlackNonPromotion, WhiteCapturesEnPassant, BlackCapturesEnPassant, - WhiteDrop, BlackDrop, FirstLeg, + WhiteDrop, BlackDrop, FirstLeg, Swap, NormalMove, AmbiguousMove, IllegalMove, ImpossibleMove, WhiteWins, BlackWins, GameIsDrawn, GameUnfinished, GNUChessGame, XBoardGame, MoveNumberOne, Open, Close, Nothing, diff --git a/moves.c b/moves.c index 032b6b0..33fda55 100644 --- a/moves.c +++ b/moves.c @@ -324,8 +324,8 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(pc == WhitePawn || pc == WhiteLance) promo = WhitePromotion, promoRank = BOARD_HEIGHT-1; else if(pc == BlackPawn || pc == BlackLance) promo = BlackPromotion, promoRank = 0; while(*p) { // more moves to go - int expo = -1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0; - char *cont = NULL; + int expo = -1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0, put = 0, u = 0; + char *cont = NULL, *q; while(*p == 'i') initial++, desc = ++p; while(islower(*p)) p++; // skip prefixes if(!isupper(*p)) return; // syntax error: no atom @@ -396,6 +396,7 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle } if(mine == 2 && tx < 0) dirSet = dirSet >> 4 | dirSet << 4 & 255; // invert black moves mode = 0; // build mode mask + if(*desc == 'u') put++, desc++; // unload stuff at start of leg if(*desc == 'm') mode |= 4, desc++; // move to empty if(*desc == 'c') mode |= his, desc++; // capture foe if(*desc == 'd') mode |= mine, desc++; // destroy (capture friend) @@ -429,6 +430,8 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle } else { strncpy(buf, cont, 80); cont = buf; // copy next leg(s), so we can modify atom = buf; while(islower(*atom)) atom++; // skip to atom + for(q=buf; q!=atom && *q != 'a'; q++) // test whether next leg unloads + if(*q == 'u') u = 1; if(mode & 32) mode ^= 256 + 32; // in non-final legs 'p' means 'pass through' if(mode & 64 + 512) { mode |= 256; // and 'g' too, but converts leaper <-> slider @@ -469,8 +472,9 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle if(occup & mode) { // valid intermediate square, do continuation char origAtom = *atom; int rg = (expo != 1 ? expo - i + 1 : range); // pass length of last *slider* leg + int transp = occup & mode & 0x104; // no side effect on intermediate square if(!(bit & all)) *atom = rotate[*atom - 'A']; // orth-diag interconversion to make direction valid - if(occup & mode & 0x104) { // no side effects, merge legs to one move + if(transp && !u) { // no side effects, merge legs to one move if(skip < 0 && occup == 4) { // create e.p. rights on this square if(viaX != 100) { // second e.p. square! if(viaX == x && viaY == y - vy) viaY = y | 128; // flag it when we can handle it @@ -479,7 +483,7 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle MovesFromString(board, flags, f, r, x, y, dir, rg, cont, cb, cl); if(viaY & 128) viaY = y - vy; else viaX = viaY = 100; } - if(occup & mode & 3 && (killX < 0 || kill2X < 0 && (legNr > 1 || killX == x && killY == y) || + if((occup & mode & 3 || transp && u) && (killX < 0 || kill2X < 0 && (legNr > 1 || killX == x && killY == y) || (legNr == 1 ? kill2X == x && kill2Y == y : killX == x && killY == y))) { // destructive first leg int cnt = 0; legNr <<= 1; @@ -524,7 +528,9 @@ MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle break; } if(mode & 16 && (board[y][x] == WhiteKing || board[y][x] == BlackKing)) break; // tame piece, cannot capture royal - if(occup & mode) cb(board, flags, y == promoRank ? promo : NormalMove, r, f, y, x, cl); // allowed, generate + if(occup & mode) { + cb(board, flags, y == promoRank ? promo : put ? Swap : NormalMove, r, f, y, x, cl); // allowed, generate + } if(occup != 4) break; // not valid transit square } while(--i); }