From ac647cc1aa823dd59b600245e5cc014ae85e1ce9 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Fri, 8 Jan 2010 10:19:32 +0100 Subject: [PATCH] Display PV on right-clicking board --- args.h | 1 + backend.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++- backend.h | 3 ++ common.h | 1 + winboard/winboard.c | 39 ++++++++++++++++----- xboard.c | 31 ++++++++++++++++- 6 files changed, 155 insertions(+), 13 deletions(-) diff --git a/args.h b/args.h index 9a5b9e9..ea1af0e 100644 --- a/args.h +++ b/args.h @@ -208,6 +208,7 @@ ArgDescriptor argDescriptors[] = { { "msLoginDelay", ArgInt, (void *) &appData.msLoginDelay, XBOARD, (ArgIniType) MS_LOGIN_DELAY }, { "pasteSelection", ArgBoolean, (void *) &appData.pasteSelection, XBOARD, (ArgIniType) FALSE }, + { "dropMenu", ArgBoolean, (void *) &appData.dropMenu, 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 dd4b0be..9cfb1a2 100644 --- a/backend.c +++ b/backend.c @@ -235,6 +235,8 @@ extern char installDir[MSG_SIZ]; extern int tinyLayout, smallLayout; ChessProgramStats programStats; +char lastPV[2][2*MSG_SIZ]; /* [HGM] pv: last PV in thinking output of each engine */ +int endPV = -1; static int exiting = 0; /* [HGM] moved to top */ static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/; int startedFromPositionFile = FALSE; Board filePosition; /* [HGM] loadPos */ @@ -4396,6 +4398,90 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) } } + +void +ParsePV(char *pv) +{ // Parse a string of PV moves, and append to current game, behind forwardMostMove + int fromX, fromY, toX, toY; char promoChar; + ChessMove moveType; + Boolean valid; + int nr = 0; + + endPV = forwardMostMove; + do { + while(*pv == ' ') pv++; + if(*pv == '(') pv++; // first (ponder) move can be in parentheses + valid = ParseOneMove(pv, endPV, &moveType, &fromX, &fromY, &toX, &toY, &promoChar); +if(appData.debugMode){ +fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, pv); +} + if(!valid && nr == 0 && + ParseOneMove(pv, endPV-1, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)){ + nr++; moveType = Comment; // First move has been played; kludge to make sure we continue + } + while(*pv && *pv++ != ' '); // skip what we parsed; assume space separators + if(moveType == Comment) { valid++; continue; } // allow comments in PV + nr++; + if(endPV+1 > framePtr) break; // no space, truncate + if(!valid) break; + endPV++; + CopyBoard(boards[endPV], boards[endPV-1]); + ApplyMove(fromX, fromY, toX, toY, promoChar, boards[endPV]); + moveList[endPV-1][0] = fromX + AAA; + moveList[endPV-1][1] = fromY + ONE; + moveList[endPV-1][2] = toX + AAA; + moveList[endPV-1][3] = toY + ONE; + parseList[endPV-1][0] = NULLCHAR; + } while(valid); +} + +static int lastX, lastY; + +Boolean +LoadPV(int x, int y) +{ // called on right mouse click to load PV + int which = gameMode == TwoMachinesPlay && (WhiteOnMove(forwardMostMove) == (second.twoMachinesColor[0] == 'w')); + lastX = x; lastY = y; + ParsePV(lastPV[which]); // load the PV of the thinking engine in the boards array. + currentMove = endPV; + if(currentMove == forwardMostMove) ClearPremoveHighlights(); else + SetPremoveHighlights(moveList[currentMove-1][0]-AAA, moveList[currentMove-1][1]-ONE, + moveList[currentMove-1][2]-AAA, moveList[currentMove-1][3]-ONE); + DrawPosition(TRUE, boards[currentMove]); + return TRUE; +} + +void +UnLoadPV() +{ + if(endPV < 0) return; + endPV = -1; + currentMove = forwardMostMove; + ClearPremoveHighlights(); + DrawPosition(TRUE, boards[currentMove]); +} + +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; + + if(endPV < 0) return; + // we must somehow check if right button is still down (might be released off board!) + if(y < margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = 1; else + if(y > h - margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = -1; else + if( y > lastY + 6 ) step = -1; else if(y < lastY - 6) step = 1; + if(!step) return; + lastX = x; lastY = y; + if(currentMove + step > endPV || currentMove + step < forwardMostMove) step = 0; + currentMove += step; + if(currentMove == forwardMostMove) ClearPremoveHighlights(); else + SetPremoveHighlights(moveList[currentMove-1][0]-AAA, moveList[currentMove-1][1]-ONE, + moveList[currentMove-1][2]-AAA, moveList[currentMove-1][3]-ONE); + DrawPosition(FALSE, boards[currentMove]); +} + + // [HGM] shuffle: a general way to suffle opening setups, applicable to arbitrary variants. // All positions will have equal probability, but the current method will not provide a unique // numbering scheme for arrays that contain 3 or more pieces of the same kind. @@ -5736,6 +5822,8 @@ void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cp stats.an_move_count = cpstats->nr_moves; } + if(stats.pv && stats.pv[0]) strcpy(lastPV[stats.which], stats.pv); // [HGM] pv: remember last PV of each + SetProgramStats( &stats ); } @@ -7709,6 +7797,7 @@ MakeMove(fromX, fromY, toX, toY, promoChar) 0, 1); return; } + UnLoadPV(); // [HGM] pv: if we are looking at a PV, abort this if (commentList[forwardMostMove+1] != NULL) { free(commentList[forwardMostMove+1]); commentList[forwardMostMove+1] = NULL; @@ -13308,12 +13397,12 @@ DecrementClocks() if(whiteNPS >= 0) lastTickLength = 0; timeRemaining = whiteTimeRemaining -= lastTickLength; DisplayWhiteClock(whiteTimeRemaining - fudge, - WhiteOnMove(currentMove)); + WhiteOnMove(currentMove < forwardMostMove ? currentMove : forwardMostMove)); } else { if(blackNPS >= 0) lastTickLength = 0; timeRemaining = blackTimeRemaining -= lastTickLength; DisplayBlackClock(blackTimeRemaining - fudge, - !WhiteOnMove(currentMove)); + !WhiteOnMove(currentMove < forwardMostMove ? currentMove : forwardMostMove)); } if (CheckFlags()) return; diff --git a/backend.h b/backend.h index f86410c..ccfd91e 100644 --- a/backend.h +++ b/backend.h @@ -205,6 +205,9 @@ double u64ToDouble P((u64 value)); void OutputChatMessage P((int partner, char *mess)); void EditPositionDone P((Boolean fakeRights)); Boolean GetArgValue P((char *name)); +Boolean LoadPV P((int x, int y)); +void UnLoadPV P(()); +void MovePV P((int x, int y, int h)); char *StrStr P((char *string, char *match)); char *StrCaseStr P((char *string, char *match)); diff --git a/common.h b/common.h index cd21c7e..6622a55 100644 --- a/common.h +++ b/common.h @@ -636,6 +636,7 @@ typedef struct { Boolean useInternalWrap; /* use internal wrapping -- noJoin usurps this if set */ Boolean pasteSelection; /* paste X selection instead of clipboard */ int nrVariations; /* [HGM] multivar */ + Boolean dropMenu; } AppData, *AppDataPtr; /* [AS] PGN tags (for showing in the game list) */ diff --git a/winboard/winboard.c b/winboard/winboard.c index 0d33b09..c3dcf97 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -3705,6 +3705,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_MOUSEMOVE: + MovePV(pt.x - boardRect.left, pt.y - boardRect.top, boardRect.bottom - boardRect.top); if ((appData.animateDragging || appData.highlightDragging) && (wParam & MK_LBUTTON) && dragInfo.from.x >= 0) @@ -3742,6 +3743,12 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ReleaseCapture(); + UnLoadPV(); + break; + case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: ErrorPopDown(); @@ -3786,15 +3793,29 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1); } break; - case IcsPlayingWhite: - case IcsPlayingBlack: - case EditGame: - case MachinePlaysWhite: - case MachinePlaysBlack: - if (appData.testLegality && - gameInfo.variant != VariantBughouse && - gameInfo.variant != VariantCrazyhouse) break; - if (x < 0 || y < 0) break; + case IcsObserving: + if(!appData.icsEngineAnalyze) break; + case IcsPlayingWhite: + case IcsPlayingBlack: + if(!appData.zippyPlay) goto noZip; + case MachinePlaysWhite: + case MachinePlaysBlack: + case TwoMachinesPlay: + case AnalyzeMode: + case AnalyzeFile: + if (!appData.dropMenu) { + SetCapture(hwndMain); + LoadPV(pt.x - boardRect.left, pt.y - boardRect.top); + break; + } + if(gameMode == TwoMachinesPlay || gameMode == AnalyzeMode || + gameMode == AnalyzeFile || gameMode == IcsObserving) break; + case EditGame: + noZip: + if (x < 0 || y < 0) break; + if (!appData.dropMenu || appData.testLegality && + gameInfo.variant != VariantBughouse && + gameInfo.variant != VariantCrazyhouse) break; fromX = x; fromY = y; hmenu = LoadMenu(hInst, "DropPieceMenu"); diff --git a/xboard.c b/xboard.c index 0dd023d..840ac50 100644 --- a/xboard.c +++ b/xboard.c @@ -256,6 +256,8 @@ void HandleUserMove P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AnimateUserMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); +void HandlePV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); void WhiteClock P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void BlackClock P((Widget w, XEvent *event, @@ -832,6 +834,8 @@ XtActionsRec boardActions[] = { { "DrawPosition", DrawPositionProc }, { "HandleUserMove", HandleUserMove }, { "AnimateUserMove", AnimateUserMove }, + { "HandlePV", HandlePV }, + { "UnLoadPV", UnLoadPV }, { "FileNameAction", FileNameAction }, { "AskQuestionProc", AskQuestionProc }, { "AskQuestionReplyAction", AskQuestionReplyAction }, @@ -988,6 +992,8 @@ char boardTranslations[] = ": HandleUserMove() \n \ : HandleUserMove() \n \ : AnimateUserMove() \n \ + : HandlePV() \n \ + : UnLoadPV() \n \ Shift: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\ PieceMenuPopup(menuB) \n \ Any: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \ @@ -3672,6 +3678,8 @@ void PieceMenuPopup(w, event, params, num_params) Cardinal *num_params; { String whichMenu; + + if (event->type != ButtonRelease) UnLoadPV(); // [HGM] pv if (event->type != ButtonPress) return; if (errorUp) ErrorPopDown(); switch (gameMode) { @@ -3679,12 +3687,25 @@ void PieceMenuPopup(w, event, params, num_params) case IcsExamining: whichMenu = params[0]; break; + case IcsObserving: + if(!appData.icsEngineAnalyze) return; case IcsPlayingWhite: case IcsPlayingBlack: - case EditGame: + if(!appData.zippyPlay) goto noZip; + case AnalyzeMode: + case AnalyzeFile: case MachinePlaysWhite: case MachinePlaysBlack: - if (appData.testLegality && + case TwoMachinesPlay: // [HGM] pv: use for showing PV + if (!appData.dropMenu) { + LoadPV(event->xbutton.x, event->xbutton.y); + return; + } + if(gameMode == TwoMachinesPlay || gameMode == AnalyzeMode || + gameMode == AnalyzeFile || gameMode == IcsObserving) return; + case EditGame: + noZip: + if (!appData.dropMenu || appData.testLegality && gameInfo.variant != VariantBughouse && gameInfo.variant != VariantCrazyhouse) return; SetupDropMenu(); @@ -4429,6 +4450,12 @@ void AnimateUserMove (Widget w, XEvent * event, DragPieceMove(event->xmotion.x, event->xmotion.y); } +void HandlePV (Widget w, XEvent * event, + String * params, Cardinal * nParams) +{ // [HGM] pv: walk PV + MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap)); +} + Widget CommentCreate(name, text, mutable, callback, lines) char *name, *text; int /*Boolean*/ mutable; -- 1.7.0.4