X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=4ceb598a7e22b07315d54b463578094883218904;hb=1514fbc6e388eb410d72a5c58a2cb371d2be0d7c;hp=3cd2f0ca7363666d5acf1d0a5d437188cbd4a329;hpb=67f4ae6657dcdff13ce494d64dcb936df3c78c1a;p=xboard.git diff --git a/backend.c b/backend.c index 3cd2f0c..4ceb598 100644 --- a/backend.c +++ b/backend.c @@ -920,6 +920,7 @@ Load (ChessProgramState *cps, int i) p[-1] = 0; appData.directory[i] = strdup(engineName); p[-1] = SLASH; + if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split! } else appData.directory[i] = "."; if(params[0]) { if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces @@ -1485,6 +1486,8 @@ MatchEvent (int mode) NextMatchGame(); } +char *comboLine = NULL; // [HGM] recent: WinBoard's first-engine combobox line + void InitBackEnd3 P((void)) { @@ -1498,7 +1501,7 @@ InitBackEnd3 P((void)) free(programVersion); programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy)); sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy); - FloatToFront(&appData.recentEngineList, appData.firstChessProgram); + FloatToFront(&appData.recentEngineList, comboLine ? comboLine : appData.firstChessProgram); } if (appData.icsActive) { @@ -2614,6 +2617,13 @@ SeekGraphClick (ClickType click, int x, int y, int moving) { static int lastDown = 0, displayed = 0, lastSecond; if(y < 0) return FALSE; + if(!(appData.seekGraph && appData.icsActive && loggedOn && + (gameMode == BeginningOfGame || gameMode == IcsIdle))) { + if(!seekGraphUp) return FALSE; + seekGraphUp = FALSE; // seek graph is up when it shouldn't be: take it down + DrawPosition(TRUE, NULL); + return TRUE; + } if(!seekGraphUp) { // initiate cration of seek graph by requesting seek-ad list if(click == Release || moving) return FALSE; nrOfSeekAds = 0; @@ -3560,7 +3570,7 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int if (looking_at(buf, &i, "% ") || ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE) && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book - if(soughtPending) { // [HGM] seekgraph: on ICC sought-list has no termination line + if(soughtPending && nrOfSeekAds) { // [HGM] seekgraph: on ICC sought-list has no termination line soughtPending = FALSE; seekGraphUp = TRUE; DrawSeekGraph(); @@ -4208,6 +4218,7 @@ ParseBoard12 (char *string) newGameMode = ((relation == RELATION_PLAYING_MYMOVE) == (to_play == 'W')) ? IcsPlayingWhite : IcsPlayingBlack; + soughtPending =FALSE; // [HGM] seekgraph: solve race condition break; case RELATION_EXAMINING: newGameMode = IcsExamining; @@ -4507,7 +4518,10 @@ ParseBoard12 (char *string) r = boards[moveNum][CASTLING][5] = initialRights[5]; } /* [HGM] e.p. rights. Assume that ICS sends file number here? */ - boards[moveNum][EP_STATUS] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT; + boards[moveNum][EP_STATUS] = EP_NONE; + if(str[0] == 'P') boards[moveNum][EP_STATUS] = EP_PAWN_MOVE; + if(strchr(move_str, 'x')) boards[moveNum][EP_STATUS] = EP_CAPTURE; + if(double_push != -1) boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT; if (ics_getting_history == H_GOT_REQ_HEADER || @@ -6391,12 +6405,16 @@ int lastLoadGameNumber = 0, lastLoadPositionNumber = 0; int lastLoadGameUseList = FALSE; char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ]; ChessMove lastLoadGameStart = EndOfFile; +int doubleClick, mappedMove = -1; void UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) { ChessMove moveType; ChessSquare pdown, pup; + static char excludeMap[(BOARD_RANKS*BOARD_FILES*BOARD_RANKS*BOARD_FILES+7)/8]; // [HGM] exclude: bitmap for excluced moves + int ff=fromX, rf=fromY, ft=toX, rt=toY; + /* 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 @@ -6532,6 +6550,18 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) return; } + if(doubleClick && (toX == -2 || toY == -2)) { // [HGM] exclude: off-board move means exclude all + int i; // note that drop moves still have holdings coords as from-square at this point + ChessMove moveType; char pc; + for(i=0; i<(BOARD_RANKS*BOARD_FILES*BOARD_RANKS*BOARD_FILES+7)/8; i++) excludeMap[i] = -(toY == -2); + mappedMove = currentMove; + if(toY != -2) { SendToProgram("include all\n", &first); return; } + SendToProgram("exclude all\n", &first); + i = ParseOneMove(lastPV[0], currentMove, &moveType, &fromX, &fromY, &toX, &toY, &pc); + ff=fromX, rf=fromY, ft=toX, rt=toY, promoChar = pc; // make copy that will survive drop encoding + if(!i) return; // kludge: continue with move changed to engine's last-reported best, so it gets included again. + } + if(toX < 0 || toY < 0) return; pdown = boards[currentMove][fromY][fromX]; pup = boards[currentMove][toY][toX]; @@ -6563,6 +6593,21 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) } } + if(doubleClick) { // [HGM] exclude: move entered with double-click on from square is for exclusion, not playing + int i=(BOARD_FILES*rf+ff)*BOARD_RANKS*BOARD_FILES + (BOARD_FILES*rt+ft), j; + char buf[MSG_SIZ]; + if(mappedMove != currentMove) + for(j=0; j<(BOARD_RANKS*BOARD_FILES*BOARD_RANKS*BOARD_FILES+7)/8; j++) excludeMap[j] = 0; + j = i%8; i >>= 3; + snprintf(buf, MSG_SIZ, "%sclude ", excludeMap[i] & 1<= gameInfo.holdingsSize) ) return; - if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered) + if(gotPremove && x == premoveFromX && y == premoveFromY && clickType == Release) { + // could be static click on premove from-square: abort premove + gotPremove = 0; + ClearPremoveHighlights(); + } + + if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered && SubtractTimeMarks(&lastClickTime, &prevClickTime) >= 200) 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 @@ -6898,6 +6948,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) } return; } + doubleClick = FALSE; fromX = x; fromY = y; toX = toY = -1; 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 @@ -6944,6 +6995,10 @@ LeftClick (ClickType clickType, int xPix, int yPix) !(fromP == BlackKing && toP == BlackRook && frc))) { /* Clicked again on same color piece -- changed his mind */ second = (x == fromX && y == fromY); + if(second && gameMode == AnalyzeMode && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) { + second = FALSE; // first double-click rather than scond click + doubleClick = first.excludeMoves; // used by UserMoveEvent to recognize exclude moves + } promoDefaultAltered = FALSE; MarkTargetSquares(1); if(!second || appData.oneClick && !OnlyMove(&x, &y, TRUE)) { @@ -6957,7 +7012,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && y == (toP < BlackPawn ? 0 : BOARD_HEIGHT-1)) gatingPiece = boards[currentMove][fromY][fromX]; - else gatingPiece = EmptySquare; + else gatingPiece = doubleClick ? fromP : EmptySquare; fromX = x; fromY = y; dragging = 1; MarkTargetSquares(0); @@ -7079,7 +7134,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) // off-board moves should not be highlighted if(x < 0 || y < 0) ClearHighlights(); - if(gatingPiece != EmptySquare) promoChoice = ToLower(PieceToChar(gatingPiece)); + if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece)); if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) { SetHighlights(fromX, fromY, toX, toY); @@ -8348,7 +8403,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. /* * If chess program startup fails, exit with an error message. - * Attempts to recover here are futile. + * Attempts to recover here are futile. [HGM] Well, we try anyway */ if ((StrStr(message, "unknown host") != NULL) || (StrStr(message, "No remote directory") != NULL) @@ -8362,7 +8417,17 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. _(cps->which), cps->program, cps->host, message); RemoveInputSource(cps->isr); if(appData.icsActive) DisplayFatalError(buf1, 0, 1); else { - if(cps == &first) appData.noChessProgram = TRUE; + cps->isr = NULL; + DestroyChildProcess(cps->pr, 9 ); // just to be sure + cps->pr = NoProc; + if(cps == &first) { + appData.noChessProgram = TRUE; + gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu + gameMode = BeginningOfGame; ModeHighlight(); + SetNCPMode(); + } + if(GetDelayedEvent()) CancelDelayedEvent(), ThawUI(); // [HGM] cancel remaining loading effort scheduled after feature timeout + DisplayMessage("", ""); // erase waiting message DisplayError(buf1, 0); } return; @@ -10688,6 +10753,7 @@ Reset (int redraw, int init) DisplayMessage("", ""); HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); lastSavedGame = 0; // [HGM] save: make sure next game counts as unsaved + mappedMove = -1; // [HGM] exclude: invalidate map } void @@ -13671,6 +13737,7 @@ EditPositionEvent () currentMove = forwardMostMove = backwardMostMove = 0; HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1); DisplayMove(-1); + if(!appData.pieceMenu) DisplayMessage(_("Click clock to clear board"), ""); } void @@ -14277,6 +14344,7 @@ ForwardInner (int target) if ( !matchMode && gameMode != Training) { // [HGM] PV info: routine tests if empty DisplayComment(currentMove - 1, commentList[currentMove]); } + mappedMove = -1; // [HGM] exclude: invalidate map } @@ -14390,6 +14458,7 @@ BackwardInner (int target) HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1); // [HGM] PV info: routine tests if comment empty DisplayComment(currentMove - 1, commentList[currentMove]); + mappedMove = -1; // [HGM] exclude: invalidate map } void @@ -15456,6 +15525,7 @@ ParseFeatures (char *args, ChessProgramState *cps) if (BoolFeature(&p, "playother", &cps->usePlayother, cps)) continue; if (BoolFeature(&p, "colors", &cps->useColors, cps)) continue; if (BoolFeature(&p, "usermove", &cps->useUsermove, cps)) continue; + if (BoolFeature(&p, "exclude", &cps->excludeMoves, cps)) continue; if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue; if (BoolFeature(&p, "name", &cps->sendName, cps)) continue; if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */