Merge branch 'master' of git://git.sv.gnu.org/xboard
authorEric Mullins <emwine@earthlink.net>
Fri, 9 Oct 2009 06:10:18 +0000 (00:10 -0600)
committerEric Mullins <emwine@earthlink.net>
Fri, 9 Oct 2009 06:10:18 +0000 (00:10 -0600)
backend.c
backend.h
winboard/winboard.c
xboard.c

index 5fb842c..ddd4ef2 100644 (file)
--- 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] <sameColor> 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);
 }
 
index d850ff7..4cc8646 100644 (file)
--- 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));
index df76074..0fa4807 100644 (file)
@@ -494,7 +494,7 @@ void ThawUI()
   DrawMenuBar(hwndMain);\r
 }\r
 \r
-static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
+/*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
 \r
 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */\r
 #ifdef JAWS\r
@@ -5120,17 +5120,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        toY = y;\r
         /* [HGM] <popupFix> UserMoveEvent requires two calls now,\r
            to make sure move is legal before showing promotion popup */\r
-        moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
+        moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, FALSE);\r
        if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
                fromX = fromY = -1; \r
                ClearHighlights();\r
                DrawPosition(FALSE, boards[currentMove]);\r
                break; \r
        } else \r
-        if(moveType != ImpossibleMove) {\r
-         if(moveType == IllegalMove) {\r
-               ;\r
-         } else\r
+        if(moveType != ImpossibleMove && moveType != Comment) {\r
           /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */\r
           if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
             ((moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
@@ -5155,9 +5152,11 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                    DrawPosition(FALSE, boards[currentMove]);\r
                    boards[currentMove][fromY][fromX] = p; // take back, but display stays\r
                    boards[currentMove][toY][toX] = q;\r
+                   DisplayMessage("Select piece from holdings", "");\r
                  } else\r
                   PromotionPopup(hwnd);\r
-          } else {       /* not a promotion */\r
+                 goto noClear;\r
+          } else { // not a promotion. Move can be illegal if testLegality off, and should be made then.\r
              if (appData.animate || appData.highlightLastMove) {\r
                  SetHighlights(fromX, fromY, toX, toY);\r
              } else {\r
@@ -5170,14 +5169,16 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
              }\r
           }\r
           fromX = fromY = -1;\r
+       noClear:\r
          break;\r
         }\r
-        if (gotPremove) {\r
+        if (gotPremove && moveType != Comment) {\r
            SetPremoveHighlights(fromX, fromY, toX, toY);\r
-            DrawPosition(forceFullRepaint || FALSE, NULL);\r
+//            DrawPosition(forceFullRepaint || FALSE, NULL);\r
        } else ClearHighlights();\r
         fromX = fromY = -1;\r
         DrawPosition(forceFullRepaint || FALSE, NULL);\r
+       if(moveType != Comment) break;\r
     }\r
     /* First downclick, or restart on a square with same color piece */\r
     if (!frozen && OKToStartUserMove(x, y)) {\r
@@ -5225,7 +5226,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       toY = y;\r
       saveAnimate = appData.animate; /* sorry, Hawk :) */\r
       appData.animate = appData.animate && !appData.animateDragging;\r
-      moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
+      moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, TRUE);\r
       if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
                fromX = fromY = -1; \r
                ClearHighlights();\r
@@ -5253,6 +5254,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                    boards[currentMove][fromY][fromX] = p; // take back, but display stays\r
                    boards[currentMove][toY][toX] = q;\r
                    appData.animate = saveAnimate;\r
+                   DisplayMessage("Select piece from holdings", "");\r
                    break;\r
                  } else\r
                PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
index e8b561d..64ac34f 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -1404,6 +1404,9 @@ XtResource clientResources[] = {
     { "keepAlive", "keepAlive", XtRInt,
        sizeof(int), XtOffset(AppDataPtr, keepAlive),
        XtRImmediate, (XtPointer) 0},
+    { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean,
+       sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal),
+       XtRImmediate, (XtPointer) False},
 };
 
 XrmOptionDescRec shellOptions[] = {
@@ -1772,6 +1775,7 @@ XrmOptionDescRec shellOptions[] = {
     { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
     { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
     { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL },
+    { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" },
 };
 
 
@@ -5131,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) {
@@ -5149,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
@@ -5167,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;
@@ -5182,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 */
@@ -5234,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;
@@ -5256,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 */
@@ -6056,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);