int gs_gamenum;
char gs_kind[MSG_SIZ];
static char player1Name[128] = "";
-static char player2Name[128] = "";\r
+static char player2Name[128] = "";
static char cont_seq[] = "\n\\ ";
static int player1Rating = -1;
static int player2Rating = -1;
}
int
-IsPromotion(fromX, fromY, toX, toY)
- int fromX, fromY, toX, toY;
+HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice)
{
+ /* [HGM] rewritten IsPromotion to only flag promotions that offer a choice */
/* [HGM] add Shogi promotions */
int promotionZoneSize=1, highestPromotingPiece = (int)WhitePawn;
ChessSquare piece;
+ ChessMove moveType;
+ Boolean premove;
+
+ if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) return FALSE; // drop
+ if(toX < BOARD_LEFT || toX >= BOARD_RGHT) return FALSE; // move into holdings
+
+ if(gameMode == EditPosition || gameInfo.variant == VariantXiangqi || // no promotions
+ !(fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0) ) // invalid move
+ return FALSE;
- if(gameMode == EditPosition || gameInfo.variant == VariantXiangqi ||
- !(fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0) ) return FALSE;
- /* [HGM] Note to self: line above also weeds out drops */
piece = boards[currentMove][fromY][fromX];
if(gameInfo.variant == VariantShogi) {
promotionZoneSize = 3;
- highestPromotingPiece = (int)WhiteKing;
- /* [HGM] Should be Silver = Ferz, really, but legality testing is off,
- and if in normal chess we then allow promotion to King, why not
- allow promotion of other piece in Shogi? */
+ highestPromotingPiece = (int)WhiteFerz;
}
+
+ // next weed out all moves that do not touch the promotion zone at all
if((int)piece >= BlackPawn) {
if(toY >= promotionZoneSize && fromY >= promotionZoneSize)
return FALSE;
if( toY < BOARD_HEIGHT - promotionZoneSize &&
fromY < BOARD_HEIGHT - promotionZoneSize) return FALSE;
}
- return ( (int)piece <= highestPromotingPiece );
+
+ if( (int)piece > highestPromotingPiece ) return FALSE; // non-promoting piece
+
+ // weed out mandatory Shogi promotions
+ if(gameInfo.variant == VariantShogi) {
+ if(piece >= BlackPawn) {
+ if(toY == 0 && piece == BlackPawn ||
+ toY == 0 && piece == BlackQueen ||
+ toY <= 1 && piece == BlackKnight) {
+ *promoChoice = '+';
+ return FALSE;
+ }
+ } else {
+ if(toY == BOARD_HEIGHT-1 && piece == WhitePawn ||
+ toY == BOARD_HEIGHT-1 && piece == WhiteQueen ||
+ toY >= BOARD_HEIGHT-2 && piece == WhiteKnight) {
+ *promoChoice = '+';
+ return FALSE;
+ }
+ }
+ }
+
+ // weed out obviously illegal Pawn moves
+ if(appData.testLegality && (piece == WhitePawn || piece == BlackPawn) ) {
+ if(toX > fromX+1 || toX < fromX-1) return FALSE; // wide
+ if(piece == WhitePawn && toY != fromY+1) return FALSE; // deep
+ if(piece == BlackPawn && toY != fromY-1) return FALSE; // deep
+ if(fromX != toX && gameInfo.variant == VariantShogi) return FALSE;
+ // note we are not allowed to test for valid (non-)capture, due to premove
+ }
+
+ // we either have a choice what to promote to, or (in Shogi) whether to promote
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier) {
+ *promoChoice = PieceToChar(BlackFerz); // no choice
+ return FALSE;
+ }
+ if(appData.alwaysPromoteToQueen) { // predetermined
+ if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantLosers)
+ *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want
+ else *promoChoice = PieceToChar(BlackQueen);
+ return FALSE;
+ }
+
+ // suppress promotion popup on illegal moves that are not premoves
+ premove = gameMode == IcsPlayingWhite && !WhiteOnMove(currentMove) ||
+ gameMode == IcsPlayingBlack && WhiteOnMove(currentMove);
+ if(appData.testLegality && !premove) {
+ moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
+ epStatus[currentMove], castlingRights[currentMove],
+ fromY, fromX, toY, toX, NULLCHAR);
+ if(moveType != WhitePromotionQueen && moveType != BlackPromotionQueen &&
+ moveType != WhitePromotionKnight && moveType != BlackPromotionKnight)
+ return FALSE;
+ }
+
+ return TRUE;
}
int
ChessMove moveType;
ChessSquare pdown, pup;
- if (fromX < 0 || fromY < 0) 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: 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 && !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 == WhiteKing && pdown == WhiteRook && fromY == 0 && toY == 0|| // also allow RxK
- pup == BlackKing && pdown == BlackRook && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 )
- ) )
- 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
tried to pick up may have been captured by the time he puts it down!
return ImpossibleMove;
}
+ pdown = boards[currentMove][fromY][fromX];
+ pup = boards[currentMove][toY][toX];
+
/* [HGM] If move started in holdings, it means a drop */
if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
if( pup != EmptySquare ) return ImpossibleMove;
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
+void LeftClick(ClickType clickType, int xPix, int yPix)
+{
+ int x, y;
+ Boolean saveAnimate;
+ static int second = 0, promotionChoice = 0;
+ char promoChoice = NULLCHAR;
+
+ if (clickType == Press) ErrorPopDown();
+
+ x = EventToSquare(xPix, BOARD_WIDTH);
+ y = EventToSquare(yPix, 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(clickType == Release) 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;
+ }
+
+ /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
+ if(clickType == Press
+ && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
+ || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
+ || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
+ return;
+
+ if (fromX == -1) {
+ if (clickType == Press) {
+ /* First square */
+ if (OKToStartUserMove(x, y)) {
+ fromX = x;
+ fromY = y;
+ second = 0;
+ DragPieceBegin(xPix, yPix);
+ if (appData.highlightDragging) {
+ SetHighlights(x, y, -1, -1);
+ }
+ }
+ }
+ return;
+ }
+
+ /* fromX != -1 */
+ if (clickType == Press && gameMode != EditPosition) {
+ ChessSquare fromP;
+ ChessSquare toP;
+ int frc;
+
+ // ignore off-board to clicks
+ if(y < 0 || x < 0) return;
+
+ /* 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 &&
+ WhitePawn <= toP && toP <= WhiteKing &&
+ !(fromP == WhiteKing && toP == WhiteRook && frc) &&
+ !(fromP == WhiteRook && toP == WhiteKing && frc)) ||
+ (BlackPawn <= fromP && fromP <= BlackKing &&
+ BlackPawn <= toP && toP <= BlackKing &&
+ !(fromP == BlackRook && toP == BlackKing && frc) && // allow also RxK as FRC castling
+ !(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(xPix, yPix);
+ }
+ return;
+ }
+ // ignore to-clicks in holdings
+ if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
+ }
+
+ if (clickType == Release && (x == fromX && y == fromY ||
+ x < BOARD_LEFT || x >= BOARD_RGHT)) {
+
+ // treat drags into holding as click on start square
+ x = fromX; y = fromY;
+
+ DragPieceEnd(xPix, yPix);
+ if (appData.animateDragging) {
+ /* Undo animation damage if any */
+ DrawPosition(FALSE, NULL);
+ }
+ if (second) {
+ /* Second up/down in same square; just abort move */
+ second = 0;
+ fromX = fromY = -1;
+ ClearHighlights();
+ gotPremove = 0;
+ ClearPremoveHighlights();
+ } else {
+ /* First upclick in same square; start click-click mode */
+ SetHighlights(x, y, -1, -1);
+ }
+ return;
+ }
+
+ /* we now have a different from- and to-square */
+ /* Completed move */
+ toX = x;
+ toY = y;
+ saveAnimate = appData.animate;
+ if (clickType == Press) {
+ /* Finish clickclick move */
+ if (appData.animate || appData.highlightLastMove) {
+ SetHighlights(fromX, fromY, toX, toY);
+ } else {
+ ClearHighlights();
+ }
+ } else {
+ /* Finish drag move */
+ if (appData.highlightLastMove) {
+ SetHighlights(fromX, fromY, toX, toY);
+ } else {
+ ClearHighlights();
+ }
+ DragPieceEnd(xPix, yPix);
+ /* Don't animate move and drag both */
+ appData.animate = FALSE;
+ }
+ if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice)) {
+ 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();
+ } else {
+ UserMoveEvent(fromX, fromY, toX, toY, promoChoice);
+ if (!appData.highlightLastMove || gotPremove) ClearHighlights();
+ if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
+ fromX = fromY = -1;
+ }
+ appData.animate = saveAnimate;
+ if (appData.animate || appData.animateDragging) {
+ /* Undo animation damage if needed */
+ DrawPosition(FALSE, NULL);
+ }
+}
+
void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cpstats )
{
// char * hint = lastHint;
void SetBlackToPlayEvent P((void));
void InitBackEnd1 P((void));
void InitBackEnd2 P((void));
-int IsPromotion P((int fromX, int fromY, int toX, int toY));
+int HasPromotionChoice P((int fromX, int fromY, int toX, int toY, char *choice));
int InPalace P((int row, int column));
int PieceForSquare P((int x, int y));
int OKToStartUserMove P((int x, int y));
void ScheduleDelayedEvent P((DelayedEventCallback cb, long millisec));
DelayedEventCallback GetDelayedEvent P((void));
void CancelDelayedEvent P((void));
+// [HGM] mouse: next six used by mouse handler, which was moved to backend
+extern int fromX, fromY, toX, toY;
+typedef enum { Press, Release } ClickType;
+void PromotionPopUp P((void));
+void DragPieceBegin P((int x, int y));
+void DragPieceEnd P((int x, int y));
+void LeftClick P((ClickType c, int x, int y));
int StartChildProcess P((char *cmdLine, char *dir, ProcRef *pr));
void DestroyChildProcess P((ProcRef pr, int/*boolean*/ signal));
* The offset boardRect.left or boardRect.top must already have been\r
* subtracted from x.\r
*/\r
-int\r
-EventToSquare(int x)\r
+int EventToSquare(x, limit)\r
+ int x;\r
{\r
if (x <= 0)\r
return -2;\r
if ((x % (squareSize + lineGap)) >= squareSize)\r
return -1;\r
x /= (squareSize + lineGap);\r
- if (x >= BOARD_SIZE)\r
+ if (x >= limit)\r
return -2;\r
return x;\r
}\r
}\r
}\r
\r
+void DragPieceBegin(int x, int y)\r
+{\r
+ dragInfo.lastpos.x = boardRect.left + x;\r
+ dragInfo.lastpos.y = boardRect.top + y;\r
+ dragInfo.from.x = fromX;\r
+ dragInfo.from.y = fromY;\r
+ dragInfo.start = dragInfo.from;\r
+ SetCapture(hwndMain);\r
+}\r
+\r
+void DragPieceEnd(int x, int y)\r
+{\r
+ ReleaseCapture();\r
+ dragInfo.start.x = dragInfo.start.y = -1;\r
+ dragInfo.from = dragInfo.start;\r
+ dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
+}\r
+\r
/* Event handler for mouse messages */\r
VOID\r
MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
POINT pt;\r
static int recursive = 0;\r
HMENU hmenu;\r
-// BOOLEAN needsRedraw = FALSE;\r
- BOOLEAN saveAnimate;\r
BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */\r
- static BOOLEAN sameAgain = FALSE, promotionChoice = FALSE;\r
- ChessMove moveType;\r
\r
if (recursive) {\r
if (message == WM_MBUTTONUP) {\r
\r
pt.x = LOWORD(lParam);\r
pt.y = HIWORD(lParam);\r
- x = EventToSquare(pt.x - boardRect.left);\r
- y = EventToSquare(pt.y - boardRect.top);\r
+ x = EventToSquare(pt.x - boardRect.left, BOARD_WIDTH);\r
+ y = EventToSquare(pt.y - boardRect.top, BOARD_HEIGHT);\r
if (!flipView && y >= 0) {\r
y = BOARD_HEIGHT - 1 - y;\r
}\r
\r
switch (message) {\r
case WM_LBUTTONDOWN:\r
- if(promotionChoice) { // we are waiting for a click to indicate promotion piece\r
- promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel\r
- if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);\r
- if(gameInfo.holdingsWidth && \r
- (WhiteOnMove(currentMove) \r
- ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0\r
- : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {\r
- // click in right holdings, for determining promotion piece\r
- ChessSquare p = boards[currentMove][y][x];\r
- if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);\r
- if(p != EmptySquare) {\r
- FinishMove(WhitePromotionQueen, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));\r
- fromX = fromY = -1;\r
- break;\r
- }\r
- }\r
- DrawPosition(FALSE, boards[currentMove]);\r
- break;\r
- }\r
- ErrorPopDown();\r
- sameAgain = FALSE;\r
- if (y == -2) {\r
- /* Downclick vertically off board; check if on clock */\r
if (PtInRect((LPRECT) &whiteRect, pt)) {\r
if (gameMode == EditPosition) {\r
SetWhiteToPlayEvent();\r
AdjustClock(!flipClock, -1);\r
}\r
}\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition((int) (forceFullRepaint || FALSE), NULL);\r
- }\r
- fromX = fromY = -1;\r
dragInfo.start.x = dragInfo.start.y = -1;\r
dragInfo.from = dragInfo.start;\r
- break;\r
- } else if (x < 0 || y < 0\r
- /* [HGM] block clicks between board and holdings */\r
- || x == BOARD_LEFT-1 || x == BOARD_RGHT\r
- || (x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize)\r
- || (x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize)\r
- /* EditPosition, empty square, or different color piece;\r
- click-click move is possible */\r
- ) {\r
- break;\r
- } else if (fromX == x && fromY == y) {\r
- /* Downclick on same square again */\r
- ClearHighlights();\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- sameAgain = TRUE; \r
- } else if (fromX != -1 &&\r
- x != BOARD_LEFT-2 && x != BOARD_RGHT+1 \r
- ) {\r
- /* Downclick on different square. */\r
- /* [HGM] if on holdings file, should count as new first click ! */\r
- /* [HGM] <sameColor> now always do UserMoveTest(), and check colors there */\r
- toX = x;\r
- 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, FALSE);\r
- if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
+ if(fromX == -1 && frozen) { // not sure where this is for\r
fromX = fromY = -1; \r
- ClearHighlights();\r
- DrawPosition(FALSE, boards[currentMove]);\r
- break; \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
- appData.alwaysPromoteToQueen)) {\r
- FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- }\r
- } else\r
- if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- /* [HGM] <popupFix> Popup calls FinishMove now.\r
- If promotion to Q is legal, all are legal! */\r
- if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
- { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];\r
- // kludge to temporarily execute move on display, without promoting yet\r
- promotionChoice = TRUE;\r
- boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank\r
- boards[currentMove][toY][toX] = p;\r
- 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
- 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
- ClearHighlights();\r
- }\r
- FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
- if (appData.animate && !appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- }\r
- }\r
- fromX = fromY = -1;\r
- noClear:\r
- break;\r
- }\r
- if (gotPremove && moveType != Comment) {\r
- SetPremoveHighlights(fromX, fromY, toX, toY);\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
- fromX = x;\r
- fromY = y;\r
- dragInfo.lastpos = pt;\r
- dragInfo.from.x = fromX;\r
- dragInfo.from.y = fromY;\r
- dragInfo.start = dragInfo.from;\r
- SetCapture(hwndMain);\r
- } else {\r
- fromX = fromY = -1;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */\r
+ break;\r
}\r
+ LeftClick(Press, pt.x - boardRect.left, pt.y - boardRect.top);\r
+ DrawPosition(TRUE, NULL);\r
break;\r
\r
case WM_LBUTTONUP:\r
- ReleaseCapture();\r
- if (fromX == -1) break;\r
- if (x == fromX && y == fromY) {\r
- dragInfo.from.x = dragInfo.from.y = -1;\r
- /* Upclick on same square */\r
- if (sameAgain) {\r
- /* Clicked same square twice: abort click-click move */\r
- fromX = fromY = -1;\r
- gotPremove = 0;\r
- ClearPremoveHighlights();\r
- } else {\r
- /* First square clicked: start click-click move */\r
- SetHighlights(fromX, fromY, -1, -1);\r
- }\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) {\r
- /* Errant click; ignore */\r
- break;\r
- } else {\r
- /* Finish drag move. */\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "release\n");\r
- }\r
- dragInfo.from.x = dragInfo.from.y = -1;\r
- toX = x;\r
- toY = y;\r
- saveAnimate = appData.animate; /* sorry, Hawk :) */\r
- appData.animate = appData.animate && !appData.animateDragging;\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
- DrawPosition(FALSE, boards[currentMove]);\r
- appData.animate = saveAnimate;\r
- break; \r
- } else \r
- if(moveType != ImpossibleMove) {\r
- /* [HGM] use move type to determine if move is promotion.\r
- Knight is Shogi kludge for mandatory promotion, Queen means choice */\r
- if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
- ((moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
- appData.alwaysPromoteToQueen)) \r
- FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
- else \r
- if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
- { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];\r
- // kludge to temporarily execute move on display, wthout promotng yet\r
- promotionChoice = TRUE;\r
- boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank\r
- boards[currentMove][toY][toX] = p;\r
- DrawPosition(FALSE, boards[currentMove]);\r
- 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
- } else {\r
- if(saveAnimate /* ^$!%@#$!$ */ && gameInfo.variant == VariantAtomic \r
- && (boards[currentMove][toY][toX] != EmptySquare || \r
- moveType == WhiteCapturesEnPassant || \r
- moveType == BlackCapturesEnPassant ) )\r
- AnimateAtomicCapture(fromX, fromY, toX, toY, 20);\r
- FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
- }\r
- }\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- appData.animate = saveAnimate;\r
- fromX = fromY = -1;\r
- if (appData.highlightDragging && !appData.highlightLastMove) {\r
- ClearHighlights();\r
- }\r
- if (appData.animate || appData.animateDragging ||\r
- appData.highlightDragging || gotPremove) {\r
- DrawPosition(forceFullRepaint || FALSE, NULL);\r
- }\r
- }\r
- dragInfo.start.x = dragInfo.start.y = -1; \r
- dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
+ LeftClick(Release, pt.x - boardRect.left, pt.y - boardRect.top);\r
+ DrawPosition(TRUE, NULL);\r
break;\r
\r
case WM_MOUSEMOVE:\r
{\r
BOOL full_repaint = FALSE;\r
\r
- sameAgain = FALSE; /* [HGM] if we drag something around, do keep square selected */\r
if (appData.animateDragging) {\r
dragInfo.pos = pt;\r
}\r
only show the popup when we are already sure the move is valid or\r
legal. We pass a faulty move type, but the kludge is that FinishMove\r
will figure out it is a promotion from the promoChar. */\r
- FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);\r
+ UserMoveEvent(fromX, fromY, toX, toY, promoChar);\r
+ fromX = fromY = -1;\r
if (!appData.highlightLastMove) {\r
ClearHighlights();\r
DrawPosition(FALSE, NULL);\r
FreeProcInstance(lpProc);\r
}\r
\r
+void\r
+PromotionPopUp()\r
+{\r
+ DrawPosition(TRUE, NULL);\r
+ PromotionPopup(hwndMain);\r
+}\r
+\r
/* Toggle ShowThinking */\r
VOID\r
ToggleShowThinking()\r
void AskQuestionProc P((Widget w, XEvent *event,
String *prms, Cardinal *nprms));
void AskQuestionPopDown P((void));
-void PromotionPopUp P((void));
void PromotionPopDown P((void));
void PromotionCallback P((Widget w, XtPointer client_data,
XtPointer call_data));
void ErrorPopDown P((void));
static char *ExpandPathName P((char *path));
static void CreateAnimVars P((void));
-static void DragPieceBegin P((int x, int y));
static void DragPieceMove P((int x, int y));
-static void DragPieceEnd P((int x, int y));
static void DrawDragPiece P((void));
char *ModeToWidgetName P((GameMode mode));
void EngineOutputUpdate( FrontEndProgramStats * stats );
String *prms;
Cardinal *nprms;
{
- int x, y;
- Boolean saveAnimate;
- 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) {
if (event->type == ButtonPress) {
XtPopdown(promotionShell);
}
}
- /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */
- if(event->type == ButtonPress
- && ( x == BOARD_LEFT-1 || x == BOARD_RGHT
- || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize
- || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
- return;
-
- if (fromX == -1) {
- if (event->type == ButtonPress) {
- /* First square, prepare to drag */
- if (OKToStartUserMove(x, y)) {
- fromX = x;
- fromY = y;
- second = 0;
- DragPieceBegin(event->xbutton.x, event->xbutton.y);
- if (appData.highlightDragging) {
- SetHighlights(x, y, -1, -1);
- }
- }
- }
- return;
- }
-
- /* fromX != -1 */
- 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 */
- DrawPosition(FALSE, NULL);
- }
- if (second) {
- /* Second up/down in same square; just abort move */
- second = 0;
- fromX = fromY = -1;
- ClearHighlights();
- gotPremove = 0;
- ClearPremoveHighlights();
- } else {
- /* First upclick in same square; start click-click mode */
- SetHighlights(x, y, -1, -1);
- }
- return;
- }
-
- 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;
- if (event->type == ButtonPress) {
- /* Finish clickclick move */
- if (appData.animate || appData.highlightLastMove) {
- SetHighlights(fromX, fromY, toX, toY);
- } else {
- ClearHighlights();
- }
- } else {
- /* Finish drag move */
- if (appData.highlightLastMove) {
- SetHighlights(fromX, fromY, toX, toY);
- } else {
- ClearHighlights();
- }
- DragPieceEnd(event->xbutton.x, event->xbutton.y);
- /* Don't animate move and drag both */
- appData.animate = FALSE;
- }
- 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;
-skipClearingFrom:
- appData.animate = saveAnimate;
- if (appData.animate || appData.animateDragging) {
- /* Undo animation damage if needed */
- DrawPosition(FALSE, NULL);
- }
+ // [HGM] mouse: the rest of the mouse handler is moved to the backend, and called here
+ if(event->type == ButtonPress) LeftClick(Press, event->xbutton.x, event->xbutton.y);
+ if(event->type == ButtonRelease) LeftClick(Release, event->xbutton.x, event->xbutton.y);
}
void AnimateUserMove (Widget w, XEvent * event,
promoChar = ToLower(name[0]);
}
- FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar);
+ UserMoveEvent(fromX, fromY, toX, toY, promoChar);
if (!appData.highlightLastMove || gotPremove) ClearHighlights();
if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);
damage[toY][toX] = True;
}
-static void
+void
DragPieceBegin(x, y)
int x; int y;
{
#endif
}
-static void
+void
DragPieceEnd(x, y)
int x; int y;
{