From 24f4d0b4219ae5528ccd0304194c091166787651 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 6 Apr 2011 23:47:58 +0200 Subject: [PATCH] Implement sweep selection of promotion piece When the option -sweepPromotions is true, a click-click promotion move will first display the default choice (usually Queen) on the promotion square. While you have the mouse button still down, you can change the piece by moving the mouse vertically. --- args.h | 1 + backend.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- common.h | 1 + xboard.c | 2 + 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/args.h b/args.h index b91d02d..3b798c2 100644 --- a/args.h +++ b/args.h @@ -212,6 +212,7 @@ ArgDescriptor argDescriptors[] = { { "dropMenu", ArgBoolean, (void *) &appData.dropMenu, TRUE, (ArgIniType) FALSE }, { "pieceMenu", ArgBoolean, (void *) &appData.pieceMenu, TRUE, (ArgIniType) TRUE }, + { "sweepPromotions", ArgBoolean, (void *) &appData.sweepSelect, TRUE, (ArgIniType) FALSE }, { "remoteShell", ArgFilename, (void *) &appData.remoteShell, FALSE, (ArgIniType) REMOTE_SHELL }, { "rsh", ArgFilename, (void *) &appData.remoteShell, FALSE, INVALID }, { "remoteUser", ArgString, (void *) &appData.remoteUser, FALSE, INVALID }, diff --git a/backend.c b/backend.c index ea0d977..e40b1ce 100644 --- a/backend.c +++ b/backend.c @@ -268,6 +268,7 @@ extern int chatCount; int chattingPartner; char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */ ChessSquare pieceSweep = EmptySquare; +ChessSquare promoSweep = EmptySquare; /* States for ics_getting_history */ #define H_FALSE 0 @@ -4813,6 +4814,44 @@ ProcessICSInitScript(f) void +Sweep(int step) +{ + ChessSquare piece = boards[currentMove][toY][toX]; + ChessSquare king = WhiteKing, pawn = WhitePawn, last = promoSweep; + if(gameInfo.variant == VariantKnightmate) king = WhiteUnicorn; + if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway) king = EmptySquare; + if(promoSweep >= BlackPawn) king = WHITE_TO_BLACK king, pawn = WHITE_TO_BLACK pawn; + if(gameInfo.variant == VariantSpartan && pawn == BlackPawn) pawn = BlackLance, king = EmptySquare; + if(gameInfo.variant == VariantShogi) pawn = EmptySquare; + do { + promoSweep += step; + if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap + else if((int)promoSweep == -1) promoSweep = WhiteKing; + else if(promoSweep == BlackPawn && step > 0) promoSweep = WhitePawn; + else if(promoSweep == WhiteKing && step < 0) promoSweep = BlackKing; + if(!step) step = 1; + } while(promoSweep == king || promoSweep == pawn || PieceToChar(promoSweep) == '.' + || gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep); + boards[currentMove][toY][toX] = promoSweep; + DrawPosition(FALSE, boards[currentMove]); + boards[currentMove][toY][toX] = piece; +} + +static int lastX, lastY; + +void PromoScroll(int x, int y) +{ + int step = 0; + if(abs(x - lastX) < 7 && abs(y - lastY) < 7) return; + if( y > lastY + 2 ) step = -1; else if(y < lastY - 2) step = 1; + if(!step) return; + lastX = x; lastY = y; + + if(promoSweep == EmptySquare) return; + Sweep(step); +} + +void NextPiece(int step) { ChessSquare piece = boards[currentMove][toY][toX]; @@ -5033,8 +5072,6 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, f DrawPosition(TRUE, boards[currentMove]); } -static int lastX, lastY; - Boolean LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end) { @@ -5752,6 +5789,10 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) // give caller the default choice even if we will not make it if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway) *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want + else if(gameInfo.variant == VariantSpartan) + *promoChoice = ToLower(PieceToChar(toY ? WhiteQueen : BlackAngel)); + else if(gameInfo.variant == VariantShogi) + *promoChoice = '+'; else *promoChoice = PieceToChar(BlackQueen); if(autoQueen) return FALSE; // predetermined @@ -6387,6 +6428,18 @@ void LeftClick(ClickType clickType, int xPix, int yPix) x = BOARD_WIDTH - 1 - x; } + if(promoSweep != EmptySquare) { + char promoChar = ToLower(PieceToChar(promoSweep)); + if(gameInfo.variant == VariantShogi) promoChar = promoSweep == boards[currentMove][fromY][fromX] ? '=' : '+'; + saveAnimate = appData.animate; appData.animate = FALSE; + UserMoveEvent(fromX, fromY, toX, toY, promoChar); + appData.animate = saveAnimate; + promoSweep = EmptySquare; + DrawPosition(FALSE, boards[currentMove]); + fromX = fromY = -1; + return; + } + if(promotionChoice) { // we are waiting for a click to indicate promotion piece if(clickType == Release) return; // ignore upclick of click-click destination promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel @@ -6582,7 +6635,13 @@ void LeftClick(ClickType clickType, int xPix, int yPix) DisplayMessage("Click in holdings to choose piece", ""); return; } - PromotionPopUp(); + if(appData.sweepSelect && clickType == Press) { + lastX = xPix; lastY = yPix; + ChessSquare piece = boards[currentMove][fromY][fromX]; + promoSweep = CharToPiece((piece >= BlackPawn ? ToLower : ToUpper)(promoChoice)); + if(promoChoice == '+') promoSweep = PROMOTED piece; + Sweep(0); + } else PromotionPopUp(); } else { int oldMove = currentMove; UserMoveEvent(fromX, fromY, toX, toY, promoChoice); diff --git a/common.h b/common.h index a82fc13..bb373ff 100644 --- a/common.h +++ b/common.h @@ -657,6 +657,7 @@ typedef struct { Boolean dropMenu; /* [HGM] pv */ Boolean markers; /* [HGM] markers */ Boolean pieceMenu; + Boolean sweepSelect; } AppData, *AppDataPtr; /* PGN tags (for showing in the game list) */ diff --git a/xboard.c b/xboard.c index 079d42b..1fbf561 100644 --- a/xboard.c +++ b/xboard.c @@ -4766,6 +4766,8 @@ void HandleUserMove(w, event, prms, nprms) void AnimateUserMove (Widget w, XEvent * event, String * params, Cardinal * nParams) { + extern ChessSquare promoSweep; + if(promoSweep != EmptySquare && appData.sweepSelect) PromoScroll(event->xmotion.x, event->xmotion.y); else DragPieceMove(event->xmotion.x, event->xmotion.y); } -- 1.7.0.4