From: H.G. Muller Date: Fri, 9 Oct 2009 03:33:39 +0000 (-0700) Subject: fixed premove recapture problem;promotion popup appearing on obviously illegal moves... X-Git-Tag: v4.4.1.20091019~50^2 X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=c2221f8b8d4d4850075ea5c770acb51a23154b68;p=xboard.git fixed premove recapture problem;promotion popup appearing on obviously illegal moves; promotions in Superchess and Great Shatranj 1) the premove recapture problem 2) the promotion popup appearing on obviously illegal moves (the 1. e2a8 problem) 3) promotions in Superchess and Great Shatranj, where the piece can now be selected from the holdings --- diff --git a/backend.c b/backend.c index 5fb842c..ddd4ef2 100644 --- a/backend.c +++ b/backend.c @@ -5052,36 +5052,36 @@ ChessMove lastLoadGameStart = (ChessMove) 0; ChessMove -UserMoveTest(fromX, fromY, toX, toY, promoChar) +UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn) int fromX, fromY, toX, toY; int promoChar; + Boolean captureOwn; { ChessMove moveType; ChessSquare pdown, pup; if (fromX < 0 || fromY < 0) return ImpossibleMove; - if ((fromX == toX) && (fromY == toY)) { - return ImpossibleMove; - } /* [HGM] suppress all moves into holdings area and guard band */ if( toX < BOARD_LEFT || toX >= BOARD_RGHT || toY < 0 ) return ImpossibleMove; /* [HGM] moved to here from winboard.c */ - /* note: this code seems to exist for filtering out some obviously illegal premoves */ + /* note: capture of own piece can be legal as drag-drop premove. For click-click it is selection of new piece. */ pdown = boards[currentMove][fromY][fromX]; pup = boards[currentMove][toY][toX]; - if ( gameMode != EditPosition && + if ( gameMode != EditPosition && !captureOwn && (WhitePawn <= pdown && pdown < BlackPawn && WhitePawn <= pup && pup < BlackPawn || BlackPawn <= pdown && pdown < EmptySquare && BlackPawn <= pup && pup < EmptySquare ) && !((gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom) && (pup == WhiteRook && pdown == WhiteKing && fromY == 0 && toY == 0|| - pup == BlackRook && pdown == BlackKing && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 ) + pup == BlackRook && pdown == BlackKing && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 || + pup == WhiteKing && pdown == WhiteRook && fromY == 0 && toY == 0|| // also allow RxK + pup == BlackKing && pdown == BlackRook && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 ) ) ) - return ImpossibleMove; + return Comment; /* Check if the user is playing in turn. This is complicated because we let the user "pick up" a piece before it is his turn. So the piece he @@ -5234,7 +5234,6 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar) moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), epStatus[currentMove], castlingRights[currentMove], fromY, fromX, toY, toX, promoChar); - /* [HGM] but possibly ignore an IllegalMove result */ if (appData.testLegality) { if (moveType == IllegalMove || moveType == ImpossibleMove) { @@ -5450,11 +5449,11 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar) FinishMove if the first part succeeded. Calls that do not need to do anything in between, can call this routine the old way. */ - ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar); + ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar, FALSE); if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar); if(moveType == AmbiguousMove) DrawPosition(FALSE, boards[currentMove]); - else if(moveType != ImpossibleMove) + else if(moveType != ImpossibleMove && moveType != Comment) FinishMove(moveType, fromX, fromY, toX, toY, promoChar); } diff --git a/backend.h b/backend.h index d850ff7..4cc8646 100644 --- a/backend.h +++ b/backend.h @@ -167,7 +167,7 @@ void BookEvent P((void)); void AboutGameEvent P((void)); void ExitEvent P((int status)); char *DefaultFileName P((char *)); -ChessMove UserMoveTest P((int fromX, int fromY, int toX, int toY, int promoChar)); +ChessMove UserMoveTest P((int fromX, int fromY, int toX, int toY, int promoChar, Boolean captureOwn)); void UserMoveEvent P((int fromX, int fromY, int toX, int toY, int promoChar)); void DecrementClocks P((void)); char *TimeString P((long millisec)); diff --git a/winboard/winboard.c b/winboard/winboard.c index df76074..0fa4807 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -494,7 +494,7 @@ void ThawUI() DrawMenuBar(hwndMain); } -static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them +/*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */ #ifdef JAWS @@ -5120,17 +5120,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) toY = y; /* [HGM] UserMoveEvent requires two calls now, to make sure move is legal before showing promotion popup */ - moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, FALSE); if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */ fromX = fromY = -1; ClearHighlights(); DrawPosition(FALSE, boards[currentMove]); break; } else - if(moveType != ImpossibleMove) { - if(moveType == IllegalMove) { - ; - } else + if(moveType != ImpossibleMove && moveType != Comment) { /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */ if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || ((moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && @@ -5155,9 +5152,11 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) DrawPosition(FALSE, boards[currentMove]); boards[currentMove][fromY][fromX] = p; // take back, but display stays boards[currentMove][toY][toX] = q; + DisplayMessage("Select piece from holdings", ""); } else PromotionPopup(hwnd); - } else { /* not a promotion */ + goto noClear; + } else { // not a promotion. Move can be illegal if testLegality off, and should be made then. if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); } else { @@ -5170,14 +5169,16 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } } fromX = fromY = -1; + noClear: break; } - if (gotPremove) { + if (gotPremove && moveType != Comment) { SetPremoveHighlights(fromX, fromY, toX, toY); - DrawPosition(forceFullRepaint || FALSE, NULL); +// DrawPosition(forceFullRepaint || FALSE, NULL); } else ClearHighlights(); fromX = fromY = -1; DrawPosition(forceFullRepaint || FALSE, NULL); + if(moveType != Comment) break; } /* First downclick, or restart on a square with same color piece */ if (!frozen && OKToStartUserMove(x, y)) { @@ -5225,7 +5226,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) toY = y; saveAnimate = appData.animate; /* sorry, Hawk :) */ appData.animate = appData.animate && !appData.animateDragging; - moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR); + moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, TRUE); if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */ fromX = fromY = -1; ClearHighlights(); @@ -5253,6 +5254,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) boards[currentMove][fromY][fromX] = p; // take back, but display stays boards[currentMove][toY][toX] = q; appData.animate = saveAnimate; + DisplayMessage("Select piece from holdings", ""); break; } else PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */ diff --git a/xboard.c b/xboard.c index ee2ba94..64ac34f 100644 --- a/xboard.c +++ b/xboard.c @@ -5135,10 +5135,40 @@ void HandleUserMove(w, event, prms, nprms) { int x, y; Boolean saveAnimate; - static int second = 0; + static int second = 0, promotionChoice = 0; + ChessMove moveType; if (w != boardWidget || errorExitStatus != -1) return; + x = EventToSquare(event->xbutton.x, BOARD_WIDTH); + y = EventToSquare(event->xbutton.y, BOARD_HEIGHT); + if (!flipView && y >= 0) { + y = BOARD_HEIGHT - 1 - y; + } + if (flipView && x >= 0) { + x = BOARD_WIDTH - 1 - x; + } + + if(promotionChoice) { // we are waiting for a click to indicate promotion piece + if(event->type == ButtonRelease) return; // ignore upclick of click-click destination + promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel + if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y); + if(gameInfo.holdingsWidth && + (WhiteOnMove(currentMove) + ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0 + : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) { + // click in right holdings, for determining promotion piece + ChessSquare p = boards[currentMove][y][x]; + if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p); + if(p != EmptySquare) { + FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p))); + fromX = fromY = -1; + return; + } + } + DrawPosition(FALSE, boards[currentMove]); + return; + } if (event->type == ButtonPress) ErrorPopDown(); if (promotionUp) { @@ -5153,15 +5183,6 @@ void HandleUserMove(w, event, prms, nprms) } } - x = EventToSquare(event->xbutton.x, BOARD_WIDTH); - y = EventToSquare(event->xbutton.y, BOARD_HEIGHT); - if (!flipView && y >= 0) { - y = BOARD_HEIGHT - 1 - y; - } - if (flipView && x >= 0) { - x = BOARD_WIDTH - 1 - x; - } - /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */ if(event->type == ButtonPress && ( x == BOARD_LEFT-1 || x == BOARD_RGHT @@ -5171,7 +5192,7 @@ void HandleUserMove(w, event, prms, nprms) if (fromX == -1) { if (event->type == ButtonPress) { - /* First square */ + /* First square, prepare to drag */ if (OKToStartUserMove(x, y)) { fromX = x; fromY = y; @@ -5186,39 +5207,8 @@ void HandleUserMove(w, event, prms, nprms) } /* fromX != -1 */ - if (event->type == ButtonPress && gameMode != EditPosition && - x >= 0 && y >= 0) { - ChessSquare fromP; - ChessSquare toP; - int frc; - - /* Check if clicking again on the same color piece */ - fromP = boards[currentMove][fromY][fromX]; - toP = boards[currentMove][y][x]; - frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom; - if ((WhitePawn <= fromP && fromP <= WhiteKing && // [HGM] this test should go, as UserMoveTest now does it. - WhitePawn <= toP && toP <= WhiteKing && - !(fromP == WhiteKing && toP == WhiteRook && frc)) || - (BlackPawn <= fromP && fromP <= BlackKing && - BlackPawn <= toP && toP <= BlackKing && - !(fromP == BlackKing && toP == BlackRook && frc))) { - /* Clicked again on same color piece -- changed his mind */ - second = (x == fromX && y == fromY); - if (appData.highlightDragging) { - SetHighlights(x, y, -1, -1); - } else { - ClearHighlights(); - } - if (OKToStartUserMove(x, y)) { - fromX = x; - fromY = y; - DragPieceBegin(event->xbutton.x, event->xbutton.y); - } - return; - } - } - if (event->type == ButtonRelease && x == fromX && y == fromY) { + /* Click on single square in stead of drag-drop */ DragPieceEnd(event->xbutton.x, event->xbutton.y); if (appData.animateDragging) { /* Undo animation damage if any */ @@ -5238,7 +5228,34 @@ void HandleUserMove(w, event, prms, nprms) return; } - /* Completed move */ + moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease); + + if (moveType == Comment) { // kludge for indicating capture-own on Press + /* Clicked again on same color piece -- changed his mind */ + /* note that re-clicking same square always hits same color piece */ + second = (x == fromX && y == fromY); + if (appData.highlightDragging) { + SetHighlights(x, y, -1, -1); + } else { + ClearHighlights(); + } + if (OKToStartUserMove(x, y)) { + fromX = x; + fromY = y; + DragPieceBegin(event->xbutton.x, event->xbutton.y); + } + return; + } + + if(moveType == AmbiguousMove) { // kludge to indicate edit-position move + fromX = fromY = -1; + ClearHighlights(); + DragPieceEnd(event->xbutton.x, event->xbutton.y); + DrawPosition(FALSE, boards[currentMove]); + return; + } + + /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */ toX = x; toY = y; saveAnimate = appData.animate; @@ -5260,22 +5277,38 @@ void HandleUserMove(w, event, prms, nprms) /* Don't animate move and drag both */ appData.animate = FALSE; } - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) { - UserMoveEvent(fromX, fromY, toX, toY, 'q'); + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) { // promotion, but no choice + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + } else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { + SetHighlights(fromX, fromY, toX, toY); + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { + // [HGM] super: promotion to captured piece selected from holdings + ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX]; + promotionChoice = TRUE; + // kludge follows to temporarily execute move on display, without promoting yet + boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank + boards[currentMove][toY][toX] = p; + DrawPosition(FALSE, boards[currentMove]); + boards[currentMove][fromY][fromX] = p; // take back, but display stays + boards[currentMove][toY][toX] = q; + DisplayMessage("Click in holdings to choose piece", ""); + return; + } + PromotionPopUp(); + goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback + } else + if(moveType != ImpossibleMove) { // valid move, but no promotion + FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); + } else { // invalid move; could have set premove + ClearHighlights(); + } if (!appData.highlightLastMove || gotPremove) ClearHighlights(); if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); fromX = fromY = -1; - } else { - SetHighlights(fromX, fromY, toX, toY); - PromotionPopUp(); - } - } else { - UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); - if (!appData.highlightLastMove || gotPremove) ClearHighlights(); - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - } +skipClearingFrom: appData.animate = saveAnimate; if (appData.animate || appData.animateDragging) { /* Undo animation damage if needed */ @@ -6060,7 +6093,7 @@ void PromotionCallback(w, client_data, call_data) promoChar = ToLower(name[0]); } - UserMoveEvent(fromX, fromY, toX, toY, promoChar); + FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar); if (!appData.highlightLastMove || gotPremove) ClearHighlights(); if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);