From: H.G.Muller Date: Fri, 28 Nov 2025 13:29:14 +0000 (+0100) Subject: Support variants that can split pieces X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=26729840f3eb64e5920fb191b08bffb5cdf126a6;p=xboard.git Support variants that can split pieces CECP is extended by a new engine-GUI command 'split', which transfers a matrix that specifies which piece should be left on the from-square after a move. This can be dependent on the moved piece type, but also on the type it promotes to. It is transferred as a matrix filled with the ID of the piece to be left behind, where rows are separated by slashes. Each row starts with the ID for non-promoting moves, and then (optionally) continues with the cases for promotion choices in pieceToCharTable order. E.g., to have a Knight leave behind Pawns in otherwise normal Chess, the engine can send: split /P//////p where non-,emmtioned and empty rows are taken to specify the from-square should be left empty. To specify promotion to Knight should actually give you two Knights (other promotions being unaffected) the engine could send split --N//////--------n The split command only works in engine-defined variants, and should be sent after 'setup' in order for the pieceToCharTable (needed to interpret it) to be known. Beware that the format allows for enemy promotion, so that the black promotion choices come late in the row. --- diff --git a/backend.c b/backend.c index 6432f8d..62f2b86 100644 --- a/backend.c +++ b/backend.c @@ -299,7 +299,7 @@ static int initPing = -1; int border; /* [HGM] width of board rim, needed to size seek graph */ char bestMove[MSG_SIZ], avoidMove[MSG_SIZ]; int solvingTime, totalTime, jawsClock; - +ChessSquare leaveBehind[EmptySquare+1][EmptySquare]; /* States for ics_getting_history */ #define H_FALSE 0 #define H_REQUESTED 1 @@ -8984,6 +8984,21 @@ LoadError (char *errmess, ChessProgramState *cps) return TRUE; } +void +ParseMatrix (char *s, ChessSquare matrix[][EmptySquare]) +{ + int i= -1, j, k; + char c = '/'; + do { + if(c == '/') { while(pieceToChar[++i] == '.') {} j = -2; continue; } + if(j == -2) { j++; k = EmptySquare; } else { + while(pieceToChar[++j] == '.') {} + k = j; + } + matrix[k][i] = CharToPiece(c); + } while((c = *s++)); +} + char *savedMessage; ChessProgramState *savedState; void @@ -9478,6 +9493,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } return; } + if(sscanf(message, "split %s" , buf1) == 1) { if(*engineVariant) ParseMatrix(buf1, leaveBehind); return;} if(sscanf(message, "choice %s", promoRestrict) == 1) { if(gameMode == BeginningOfGame && cps == &first && (!appData.testLegality || *engineVariant != NULLCHAR || gameInfo.variant == VariantFairy)) { @@ -10552,7 +10568,7 @@ ParseGameHistory (char *game) void ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) { - ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; + ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2, left; int p, rookX, oldEP, epRank, epFile, lastFile, lastRank, berolina = 0, isEP = 0; int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1; @@ -10927,6 +10943,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) && pieceToChar[PROMOTED(newPiece)] == '~') newPiece = PROMOTED(newPiece);// but promoted version available board[toY][toX] = newPiece; } + left = leaveBehind[promoChar ? board[toY][toX] : EmptySquare][piece]; // [HGM] for variants that split pieces + if(left != EmptySquare) board[fromY][fromX] = left; // make sure this does not interfere unless split command was received if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) && promoChar != NULLCHAR && gameInfo.holdingsSize) { // [HGM] superchess: take promotion piece out of holdings @@ -12456,7 +12474,7 @@ ResurrectChessProgram () void Reset (int redraw, int init) { - int i; + int i, j; if (appData.debugMode) { fprintf(debugFP, "Reset(%d, %d) from gameMode %d\n", @@ -12467,6 +12485,7 @@ Reset (int redraw, int init) handSize = 0; prelude = FALSE; preludeText[0] = NULLCHAR; for(i=0; i