From 14fa496aee4fc5ff4288ac254937a0cab78c12eb Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Sat, 9 Apr 2011 11:42:21 +0200 Subject: [PATCH] Third method of sweep selection This method sweeps through the possible promotion choices for the piece that is being dragged, as long as you drag a 7th-rank Pawn backwards. On draggin such a Pawn forwards, it immediately shows it as the piece you are going to promote to. --- backend.c | 121 +++++++++++++++++++------------------------------- backend.h | 1 + frontend.h | 1 + winboard/winboard.c | 16 +++++-- xboard.c | 10 ++++ xoptions.c | 2 +- 6 files changed, 70 insertions(+), 81 deletions(-) diff --git a/backend.c b/backend.c index c0d36aa..3f36345 100644 --- a/backend.c +++ b/backend.c @@ -268,7 +268,7 @@ extern int chatCount; int chattingPartner; char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */ ChessSquare pieceSweep = EmptySquare; -ChessSquare promoSweep = EmptySquare, defaultPromoChoice, savePiece = EmptySquare; +ChessSquare promoSweep = EmptySquare, defaultPromoChoice; int promoDefaultAltered; /* States for ics_getting_history */ @@ -4814,9 +4814,7 @@ ProcessICSInitScript(f) } -static int lastX, lastY, selectFlag, dragging, sweepX, sweepY; -static ChessSquare substitute = EmptySquare; -static char defaultPromoChar; +static int lastX, lastY, selectFlag, dragging; void Sweep(int step) @@ -4826,7 +4824,7 @@ Sweep(int step) 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(toY != BOARD_HEIGHT-1 && toY != 0) pawn = EmptySquare; + if(fromY != BOARD_HEIGHT-2 && fromY != 1) pawn = EmptySquare; do { promoSweep -= step; if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap @@ -4837,30 +4835,22 @@ Sweep(int step) } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn || appData.testLegality && (promoSweep == king || gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep)); - boards[currentMove][sweepY][sweepX] = promoSweep; - DrawPosition(FALSE, boards[currentMove]); + ChangeDragPiece(promoSweep); } int PromoScroll(int x, int y) { int step = 0; + if(promoSweep == EmptySquare || !appData.sweepSelect) return FALSE; - if(!selectFlag) { - if(y - lastY < 4 && lastY - y < 4) return FALSE; // assume dragging until significant distance - if(substitute != EmptySquare && ((promoSweep >= BlackPawn) == flipView ? y <= lastY : y >= lastY)) { // we started dragging - defaultPromoChar = ToLower(PieceToChar(promoSweep)); // fix choice - promoSweep = EmptySquare; - return FALSE; - } - DragPieceEnd(x, y); dragging = 0; - selectFlag = 1; // we committed to sweep-selecting - } - if(abs(x - lastX) < 7 && abs(y - lastY) < 7) return TRUE; + if(abs(x - lastX) < 15 && abs(y - lastY) < 15) return FALSE; if( y > lastY + 2 ) step = -1; else if(y < lastY - 2) step = 1; - if(!step) return TRUE; + if(!step) return FALSE; lastX = x; lastY = y; - Sweep(step); - return TRUE; + if((promoSweep < BlackPawn) == flipView) step = -step; + if(step > 0) selectFlag = 1; + if(!selectFlag) Sweep(step); + return FALSE; } void @@ -5127,9 +5117,10 @@ UnLoadPV() void MovePV(int x, int y, int h) { // step through PV based on mouse coordinates (called on mouse move) - int margin = h>>3, step = 0, dist; + int margin = h>>3, step = 0; // we must somehow check if right button is still down (might be released off board!) + if(endPV < 0 && pieceSweep == EmptySquare) return; // needed in XBoard because lastX/Y is shared :-( 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; @@ -5813,14 +5804,12 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) *promoChoice = PieceToChar(BlackQueen); // Queen as good as any return FALSE; } - // with sweep-selection we take the selected default - if(appData.sweepSelect) { - *promoChoice = defaultPromoChar; - return FALSE; - } // give caller the default choice even if we will not make it *promoChoice = ToLower(PieceToChar(defaultPromoChoice)); if(gameInfo.variant == VariantShogi) *promoChoice = '+'; + if(appData.sweepSelect && gameInfo.variant != VariantGreat + && gameInfo.variant != VariantShogi + && gameInfo.variant != VariantSuper) return FALSE; if(autoQueen) return FALSE; // predetermined // suppress promotion popup on illegal moves that are not premoves @@ -6433,16 +6422,21 @@ ChessSquare gatingPiece = EmptySquare; // exported to front-end, for dragging int CanPromote(ChessSquare piece, int y) { + if(gameMode == EditPosition) return FALSE; // no promotions when editing position + // some variants have fixed promotion piece, no promotion at all, or another selection mechanism + if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantXiangqi || + gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || + gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || + gameInfo.variant == VariantMakruk) return FALSE; return (piece == BlackPawn && y == 1 || piece == WhitePawn && y == BOARD_HEIGHT-2 || - gameInfo.variant != VariantSuper && - (piece == BlackLance && y == 1 || - piece == WhiteLance && y == BOARD_HEIGHT-2) ); + piece == BlackLance && y == 1 || + piece == WhiteLance && y == BOARD_HEIGHT-2 ); } void LeftClick(ClickType clickType, int xPix, int yPix) { - int x, y, canPromote; + int x, y; Boolean saveAnimate; static int second = 0, promotionChoice = 0; char promoChoice = NULLCHAR; @@ -6467,21 +6461,10 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } if(promoSweep != EmptySquare) { // up-click during sweep-select of promo-piece - defaultPromoChar = ToLower(PieceToChar(defaultPromoChoice = promoSweep)); - if(gameInfo.variant == VariantShogi) defaultPromoChar = (promoSweep == boards[currentMove][fromY][fromX] ? '=' : '+'); + defaultPromoChoice = promoSweep; promoSweep = EmptySquare; // terminate sweep promoDefaultAltered = TRUE; - if(savePiece != EmptySquare) { - boards[currentMove][sweepY][sweepX] = savePiece; savePiece = EmptySquare; - clickType = Press; x = toX; y = toY; // fake up-click on to-square to finish one-click move - } else x = fromX, y = fromY; // and fake up-click on same square otherwise - } - - if(substitute != EmptySquare) { - boards[currentMove][fromY][fromX] = substitute; - substitute = EmptySquare; - DragPieceEnd(xPix, yPix); dragging = 0; - DrawPosition(FALSE, boards[currentMove]); + if(!selectFlag) x = fromX, y = fromY; // and fake up-click on same square if we were still selecting } if(promotionChoice) { // we are waiting for a click to indicate promotion piece @@ -6513,17 +6496,18 @@ void LeftClick(ClickType clickType, int xPix, int yPix) return; if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered) - fromX = fromY = -1; // second click on piece after altering default treated as first click + fromX = fromY = -1; // second click on piece after altering default promo piece treated as first click - if(!promoDefaultAltered) { // determine default promotion piece, based on the side the user is moving for + if(!promoDefaultAltered) { // determine default promotion piece, based on the side the user is moving for int side = (gameMode == IcsPlayingWhite || gameMode == MachinePlaysBlack || gameMode != MachinePlaysWhite && gameMode != IcsPlayingBlack && WhiteOnMove(currentMove)); defaultPromoChoice = DefaultPromoChoice(side); - } + } autoQueen = appData.alwaysPromoteToQueen; if (fromX == -1) { + int originalY = y; gatingPiece = EmptySquare; if (clickType != Press) { if(dragging) { // [HGM] from-square must have been reset due to game end since last press @@ -6532,29 +6516,23 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } return; } - if(appData.oneClick && OnlyMove(&x, &y, FALSE)) { - if(appData.sweepSelect && CanPromote(boards[currentMove][fromY][fromX], fromY)) { - promoSweep = defaultPromoChoice; - savePiece = boards[currentMove][sweepY = toY = y][sweepX = toX = x]; - selectFlag = 0; lastX = xPix; lastY = yPix; - Sweep(0); // Pawn that is going to promote: preview promotion piece - return; - } - } else { + fromX = x; fromY = y; + if(!appData.oneClick || !OnlyMove(&x, &y, FALSE) || + // even if only move, we treat as normal when this would trigger a promotion popup, to allow sweep selection + appData.sweepSelect && CanPromote(boards[currentMove][fromY][fromX], fromY) && originalY != y) { /* First square */ - if (OKToStartUserMove(x, y)) { - sweepX = fromX = x; - sweepY = fromY = y; + if (OKToStartUserMove(fromX, fromY)) { second = 0; MarkTargetSquares(0); - if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) { + DragPieceBegin(xPix, yPix); dragging = 1; + if(appData.sweepSelect && CanPromote(piece = boards[currentMove][fromY][fromX], fromY)) { promoSweep = defaultPromoChoice; - substitute = piece; selectFlag = 0; lastX = xPix; lastY = yPix; + selectFlag = 0; lastX = xPix; lastY = yPix; Sweep(0); // Pawn that is going to promote: preview promotion piece + DisplayMessage("", _("Pull pawn backwards to under-promote")); } - DragPieceBegin(xPix, yPix); dragging = 1; if (appData.highlightDragging) { - SetHighlights(x, y, -1, -1); + SetHighlights(fromX, fromY, -1, -1); } } return; @@ -6597,15 +6575,15 @@ void LeftClick(ClickType clickType, int xPix, int yPix) y == (toP < BlackPawn ? 0 : BOARD_HEIGHT-1)) gatingPiece = boards[currentMove][fromY][fromX]; else gatingPiece = EmptySquare; - sweepX = fromX = x; - sweepY = fromY = y; dragging = 1; + fromX = x; + fromY = y; dragging = 1; MarkTargetSquares(0); + DragPieceBegin(xPix, yPix); if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) { promoSweep = defaultPromoChoice; - substitute = piece; selectFlag = 0; lastX = xPix; lastY = yPix; + selectFlag = 0; lastX = xPix; lastY = yPix; Sweep(0); // Pawn that is going to promote: preview promotion piece } - DragPieceBegin(xPix, yPix); } } if(x == fromX && y == fromY) return; // if OnlyMove altered (x,y) we go on @@ -6707,14 +6685,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) DisplayMessage("Click in holdings to choose piece", ""); return; } - if(appData.sweepSelect && clickType == Press) { - lastX = xPix; lastY = yPix; - ChessSquare piece = boards[currentMove][fromY][fromX]; - promoSweep = defaultPromoChoice; - if(gameInfo.variant == VariantShogi) promoSweep = PROMOTED piece; - sweepX = toX; sweepY = toY; - selectFlag = 1; Sweep(0); - } else PromotionPopUp(); + PromotionPopUp(); } else { int oldMove = currentMove; UserMoveEvent(fromX, fromY, toX, toY, promoChoice); diff --git a/backend.h b/backend.h index d0144ef..419a1b1 100644 --- a/backend.h +++ b/backend.h @@ -228,6 +228,7 @@ Boolean LoadPV P((int x, int y)); Boolean LoadMultiPV P((int x, int y, char *buf, int index, int *start, int *end)); void UnLoadPV P(()); void MovePV P((int x, int y, int h)); +int PromoScroll P((int x, int y)); char *StrStr P((char *string, char *match)); char *StrCaseStr P((char *string, char *match)); diff --git a/frontend.h b/frontend.h index 490ef8c..50906f0 100644 --- a/frontend.h +++ b/frontend.h @@ -198,6 +198,7 @@ void AnimateMove P((Board board, int fromX, int fromY, int toX, int toY)); void HistorySet P((char movelist[][2*MOVE_LEN], int first, int last, int current)); void FreezeUI P((void)); void ThawUI P((void)); +void ChangeDragPiece P((ChessSquare piece)); extern char *programName; extern int commentUp; diff --git a/winboard/winboard.c b/winboard/winboard.c index 318f33e..a1fe6ed 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -123,9 +123,10 @@ typedef struct { POINT pos; /* window coordinates of current pos */ POINT lastpos; /* window coordinates of last pos - used for clipping */ POINT from; /* board coordinates of the piece's orig pos */ + ChessSquare piece; } DragInfo; -static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} }; +static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, EmptySquare }; typedef struct { POINT sq[2]; /* board coordinates of from, to squares */ @@ -3796,8 +3797,8 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board) board[dragInfo.from.y][dragInfo.from.x] = dragged_piece; x = dragInfo.pos.x - squareSize / 2; y = dragInfo.pos.y - squareSize / 2; - DrawPieceOnDC(hdcmem, dragged_piece, - ((int) dragged_piece < (int) BlackPawn), + DrawPieceOnDC(hdcmem, dragInfo.piece, + ((int) dragInfo.piece < (int) BlackPawn), (dragInfo.from.y + dragInfo.from.x) % 2, x, y, tmphdc); } @@ -4063,6 +4064,7 @@ void DragPieceBegin(int x, int y) dragInfo.lastpos.y = boardRect.top + y; dragInfo.from.x = fromX; dragInfo.from.y = fromY; + dragInfo.piece = boards[currentMove][fromY][fromX]; dragInfo.start = dragInfo.from; SetCapture(hwndMain); } @@ -4075,6 +4077,11 @@ void DragPieceEnd(int x, int y) dragInfo.pos = dragInfo.lastpos = dragInfo.start; } +void ChangeDragPiece(ChessSquare piece) +{ + dragInfo.piece = piece; +} + /* Event handler for mouse messages */ VOID MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) @@ -4084,7 +4091,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) static int recursive = 0; HMENU hmenu; BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */ - extern ChessSquare promoSweep; if (recursive) { if (message == WM_MBUTTONUP) { @@ -4136,7 +4142,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_MOUSEMOVE: if(SeekGraphClick(Press, pt.x - boardRect.left, pt.y - boardRect.top, 1)) break; - if(promoSweep != EmptySquare && appData.sweepSelect) { PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top); break; } + if(PromoScroll(pt.x - boardRect.left, pt.y - boardRect.top)) break; MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top); if ((appData.animateDragging || appData.highlightDragging) && (wParam & MK_LBUTTON) diff --git a/xboard.c b/xboard.c index d8faa09..6584d2a 100644 --- a/xboard.c +++ b/xboard.c @@ -8534,6 +8534,16 @@ DragPieceBegin(x, y) } } +void +ChangeDragPiece(ChessSquare piece) +{ + Pixmap mask; + player.dragPiece = piece; + /* The piece will be drawn using its own bitmap as a matte */ + SelectGCMask(piece, &player.pieceGC, &player.outlineGC, &mask); + XSetClipMask(xDisplay, player.pieceGC, mask); +} + static void DragPieceMove(x, y) int x; int y; diff --git a/xoptions.c b/xoptions.c index 37e6838..16576f9 100644 --- a/xoptions.c +++ b/xoptions.c @@ -807,7 +807,7 @@ void GeneralOptionsOK(int n) } Option generalOptions[] = { -{ 0, 0, 0, NULL, (void*) &appData.alwaysPromoteToQueen, "", NULL, CheckBox, _("Always Queen") }, +{ 0, 0, 0, NULL, (void*) &appData.sweepSelect, "", NULL, CheckBox, _("Almost Always Queen (Detour Under-Promote)") }, { 0, 0, 0, NULL, (void*) &appData.animateDragging, "", NULL, CheckBox, _("Animate Dragging") }, { 0, 0, 0, NULL, (void*) &appData.animate, "", NULL, CheckBox, _("Animate Moving") }, { 0, 0, 0, NULL, (void*) &appData.autoCallFlag, "", NULL, CheckBox, _("Auto Flag") }, -- 1.7.0.4