X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=f806abe3d1dfc9cfabf13ffe32ef510b8cd9ac4b;hb=18c9024957df2892adb21cd851cb7a27b9502d54;hp=4ac6084df9cfef290670bd5718a95f48844ed8df;hpb=3018a62f2d049e7295b703ce7780a9bd2c547ada;p=xboard.git diff --git a/backend.c b/backend.c index 4ac6084..f806abe 100644 --- a/backend.c +++ b/backend.c @@ -2089,7 +2089,7 @@ PlotSeekAd(int i) if(r > maxRating) r = maxRating; if(tc < 1.) tc = 1.; if(tc > 95.) tc = 95.; - x = (w-hMargin)* log(tc)/log(100.) + hMargin; + x = (w-hMargin-squareSize/8-7)* log(tc)/log(95.) + hMargin; y = ((double)r - minRating)/(maxRating - minRating) * (h-vMargin-squareSize/8-1) + vMargin; if(ratingList[i] < 0) y = vMargin + squareSize/4; @@ -2201,7 +2201,7 @@ DrawSeekGraph() } DrawSeekText("unrated", hMargin+squareSize/8+7, h-1-vMargin-squareSize/4); for(i=1; i<100; i+=(i<10?1:5)) { - int xx = (w-hMargin)* log((double)i)/log(100.) + hMargin; + int xx = (w-hMargin-squareSize/8-7)* log((double)i)/log(95.) + hMargin; DrawSeekAxis(xx, h-1-vMargin, xx, h-6-vMargin-3*(i%10==0)); // TC ticks if(i<=5 || (i>40 ? i%20 : i%10) == 0) { char buf[MSG_SIZ]; @@ -2237,15 +2237,16 @@ int SeekGraphClick(ClickType click, int x, int y, int moving) DisplayMessage(second ? "!" : "", seekAdList[closest]); lastSecond = second; displayed = closest; } - sprintf(buf, "play %d\n", seekNrList[closest]); if(click == Press) { if(moving == 2) zList[closest] = 100; // right-click; push to back on press lastDown = closest; return TRUE; } // on press 'hit', only show info if(moving == 2) return TRUE; // ignore right up-clicks on dot + sprintf(buf, "play %d\n", seekNrList[closest]); SendToICS(ics_prefix); - SendToICS(buf); // should this be "sought all"? + SendToICS(buf); + return TRUE; // let incoming board of started game pop down the graph } else if(click == Release) { // release 'miss' is ignored zList[lastDown] = 100; // make future selection of the rejected ad more difficult if(moving == 2) { // right up-click @@ -2541,6 +2542,7 @@ read_from_ics(isr, closure, data, count, error) sprintf(mess, "%s%s", talker, parse); OutputChatMessage(chattingPartner, mess); chattingPartner = -1; + next_out = i+1; // [HGM] suppress printing in ICS window } else if(!suppressKibitz) // [HGM] kibitz AppendComment(forwardMostMove, StripHighlight(parse), TRUE); @@ -2564,12 +2566,12 @@ read_from_ics(isr, closure, data, count, error) pvInfoList[forwardMostMove-1].score = 100*score; } OutputKibitz(suppressKibitz, parse); - next_out = i+1; // [HGM] suppress printing in ICS window } else { char tmp[MSG_SIZ]; sprintf(tmp, _("your opponent kibitzes: %s"), parse); SendToPlayer(tmp, strlen(tmp)); } + next_out = i+1; // [HGM] suppress printing in ICS window } started = STARTED_NONE; } else { @@ -2585,6 +2587,7 @@ read_from_ics(isr, closure, data, count, error) continue; } started = STARTED_NONE; + if(suppressKibitz) next_out = i+1; } /* Kludge to deal with rcmd protocol */ @@ -2642,10 +2645,12 @@ read_from_ics(isr, closure, data, count, error) continue; } + oldi = i; // [HGM] seekgraph: recognize sought lines and end-of-sought message if(appData.seekGraph) { if(soughtPending && MatchSoughtLine(buf+i)) { i = strstr(buf+i, "rated") - buf; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); next_out = leftover_start = i; started = STARTED_CHATTER; suppressKibitz = TRUE; @@ -2665,16 +2670,19 @@ read_from_ics(isr, closure, data, count, error) AddAd(star_match[0], star_match[1], atoi(star_match[2+s]), atoi(star_match[3+s]), star_match[4+s][0], star_match[5-3*s], atoi(star_match[7]), TRUE); looking_at(buf, &i, "*% "); // eat prompt + if(oldi > 0 && buf[oldi-1] == '\n') oldi--; // suppress preceding LF, if any + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); next_out = i; // suppress continue; } - if(looking_at(buf, &i, "Ads removed: *\n") || looking_at(buf, &i, "\031(51 * *\031)")) { + if(looking_at(buf, &i, "\nAds removed: *\n") || looking_at(buf, &i, "\031(51 * *\031)")) { char *p = star_match[0]; while(*p) { if(seekGraphUp) RemoveSeekAd(atoi(p)); while(*p && *p++ != ' '); // next } looking_at(buf, &i, "*% "); // eat prompt + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); next_out = i; continue; } @@ -2689,7 +2697,6 @@ read_from_ics(isr, closure, data, count, error) continue; } - oldi = i; // [HGM] kibitz: try to recognize opponent engine-score kibitzes, to divert them to engine-output window if (appData.autoKibitz && started == STARTED_NONE && !appData.icsEngineAnalyze && // [HGM] [DM] ICS analyze @@ -2698,6 +2705,8 @@ read_from_ics(isr, closure, data, count, error) (StrStr(star_match[0], gameInfo.white) == star_match[0] || StrStr(star_match[0], gameInfo.black) == star_match[0] )) { // kibitz of self or opponent suppressKibitz = TRUE; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); + next_out = i; if((StrStr(star_match[0], gameInfo.white) == star_match[0] && (gameMode == IcsPlayingWhite)) || (StrStr(star_match[0], gameInfo.black) == star_match[0] @@ -2712,24 +2721,32 @@ read_from_ics(isr, closure, data, count, error) } continue; } else - if(looking_at(buf, &i, "kibitzed to *\n") && atoi(star_match[0])) { + if((looking_at(buf, &i, "\nkibitzed to *\n") || looking_at(buf, &i, "kibitzed to *\n") || + looking_at(buf, &i, "\n(kibitzed to *\n") || looking_at(buf, &i, "(kibitzed to *\n")) + && atoi(star_match[0])) { // suppress the acknowledgements of our own autoKibitz char *p; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); if(p = strchr(star_match[0], ' ')) p[1] = NULLCHAR; // clip off "players)" on FICS SendToPlayer(star_match[0], strlen(star_match[0])); - looking_at(buf, &i, "*% "); // eat prompt + if(looking_at(buf, &i, "*% ")) // eat prompt + suppressKibitz = FALSE; next_out = i; + continue; } } // [HGM] kibitz: end of patch -//if(appData.debugMode) fprintf(debugFP, "hunt for tell, buf = %s\n", buf+i); - // [HGM] chat: intercept tells by users for which we have an open chat window channel = -1; if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") || looking_at(buf, &i, "* whispers:") || + looking_at(buf, &i, "* shouts:") || + looking_at(buf, &i, "* c-shouts:") || + looking_at(buf, &i, "--> * ") || looking_at(buf, &i, "*(*):") && (sscanf(star_match[1], "%d", &channel),1) || - looking_at(buf, &i, "*(*)(*):") && sscanf(star_match[2], "%d", &channel) == 1 )) { + looking_at(buf, &i, "*(*)(*):") && (sscanf(star_match[2], "%d", &channel),1) || + looking_at(buf, &i, "*(*)(*)(*):") && (sscanf(star_match[3], "%d", &channel),1) || + looking_at(buf, &i, "*(*)(*)(*)(*):") && sscanf(star_match[4], "%d", &channel) == 1 )) { int p; sscanf(star_match[0], "%[^(]", talker+1); // strip (C) or (U) off ICS handle chattingPartner = -1; @@ -2738,26 +2755,40 @@ read_from_ics(isr, closure, data, count, error) for(p=0; p') // shout, c-shout or it; look if there is a 'shouts' chatbox + for(p=0; p') { talker[0] = '<'; strcat(talker, "> "); Colorize(ColorShout, FALSE); } + else if(buf[i-8] == '-') { talker[0] = '('; strcat(talker, ") "); Colorize(ColorSShout, FALSE); } + else { talker[0] = '['; strcat(talker, "] "); Colorize(ColorShout, FALSE); } + chattingPartner = p; break; + } } if(chattingPartner<0) // if not, look if there is a chatbox for this indivdual for(p=0; p 0 && buf[oldi-1] == '\n') oldi--; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); started = STARTED_COMMENT; parse_pos = 0; parse[0] = NULLCHAR; savingComment = 3 + chattingPartner; // counts as TRUE suppressKibitz = TRUE; + continue; } } // [HGM] chat: end of patch @@ -3566,8 +3597,8 @@ read_from_ics(isr, closure, data, count, error) if (appData.debugMode) fprintf(debugFP, "Parsing holdings: %s, currentMove = %d\n", parse, currentMove); - if (sscanf(parse, " game %d", &gamenum) == 1 && - gamenum == ics_gamenum) { + if (sscanf(parse, " game %d", &gamenum) == 1) { + if(gamenum == ics_gamenum) { // [HGM] bughouse: old code if part of foreground game if (gameInfo.variant == VariantNormal) { /* [HGM] We seem to switch variant during a game! * Presumably no holdings were displayed, so we have @@ -3616,9 +3647,20 @@ read_from_ics(isr, closure, data, count, error) gameInfo.white, white_holding, gameInfo.black, black_holding); } - + if(!partnerUp) // [HGM] bughouse: when peeking at partner game we already know what he captured... DrawPosition(FALSE, boards[currentMove]); DisplayTitle(str); + } else if(appData.bgObserve) { // [HGM] bughouse: holdings of other game => background + sscanf(parse, "game %d white [%s black [%s <- %s", + &gamenum, white_holding, black_holding, + new_piece); + white_holding[strlen(white_holding)-1] = NULLCHAR; + black_holding[strlen(black_holding)-1] = NULLCHAR; + /* [HGM] copy holdings to partner-board holdings area */ + CopyHoldings(partnerBoard, white_holding, WhitePawn); + CopyHoldings(partnerBoard, black_holding, BlackPawn); + if(partnerUp) DrawPosition(FALSE, partnerBoard); + } } /* Suppress following prompt */ if (looking_at(buf, &i, "*% ")) { @@ -4523,6 +4565,73 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY) } void +UploadGameEvent() +{ // [HGM] upload: send entire stored game to ICS as long-algebraic moves. + int i, last = forwardMostMove; // make sure ICS reply cannot pre-empt us by clearing fmm + static char *castlingStrings[4] = { "none", "kside", "qside", "both" }; + if(gameMode == IcsObserving || gameMode == IcsPlayingBlack || gameMode == IcsPlayingWhite) { + DisplayError("You cannot do this while you are playing or observing", 0); + return; + } + if(gameMode != IcsExamining) { // is this ever not the case? + char buf[MSG_SIZ], *p, *fen, command[MSG_SIZ], bsetup = 0; + + if(ics_type == ICS_ICC) { // on ICC match ourselves in applicable variant + sprintf(command, "match %s", ics_handle); + } else { // on FICS we must first go to general examine mode + strcpy(command, "examine\nbsetup"); // and specify variant within it with bsetups + } + if(gameInfo.variant != VariantNormal) { + // try figure out wild number, as xboard names are not always valid on ICS + for(i=1; i<=36; i++) { + sprintf(buf, "wild/%d", i); + if(StringToVariant(buf) == gameInfo.variant) break; + } + if(i<=36 && ics_type == ICS_ICC) sprintf(buf, "%s w%d\n", command, i); + else if(i == 22) sprintf(buf, "%s fr\n", command); + else sprintf(buf, "%s %s\n", command, VariantName(gameInfo.variant)); + } else sprintf(buf, "%s\n", ics_type == ICS_ICC ? command : "examine\n"); // match yourself or examine + SendToICS(ics_prefix); + SendToICS(buf); + if(startedFromSetupPosition || backwardMostMove != 0) { + fen = PositionToFEN(backwardMostMove, NULL); + if(ics_type == ICS_ICC) { // on ICC we can simply send a complete FEN to set everything + sprintf(buf, "loadfen %s\n", fen); + SendToICS(buf); + } else { // FICS: everything has to set by separate bsetup commands + p = strchr(fen, ' '); p[0] = NULLCHAR; // cut after board + sprintf(buf, "bsetup fen %s\n", fen); + SendToICS(buf); + if(!WhiteOnMove(backwardMostMove)) { + SendToICS("bsetup tomove black\n"); + } + i = (strchr(p+3, 'K') != NULL) + 2*(strchr(p+3, 'Q') != NULL); + sprintf(buf, "bsetup wcastle %s\n", castlingStrings[i]); + SendToICS(buf); + i = (strchr(p+3, 'k') != NULL) + 2*(strchr(p+3, 'q') != NULL); + sprintf(buf, "bsetup bcastle %s\n", castlingStrings[i]); + SendToICS(buf); + i = boards[backwardMostMove][EP_STATUS]; + if(i >= 0) { // set e.p. + sprintf(buf, "bsetup eppos %c\n", i+AAA); + SendToICS(buf); + } + bsetup++; + } + } + if(bsetup || ics_type != ICS_ICC && gameInfo.variant != VariantNormal) + SendToICS("bsetup done\n"); // switch to normal examining. + } + for(i = backwardMostMove; i framePtr) break; // no space, truncate if(!valid) break; @@ -4738,7 +4867,13 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+ moveList[endPV-1][1] = fromY + ONE; moveList[endPV-1][2] = toX + AAA; moveList[endPV-1][3] = toY + ONE; - parseList[endPV-1][0] = NULLCHAR; + if(storeComments) + CoordsToAlgebraic(boards[endPV - 1], + PosFlags(endPV - 1), + fromY, fromX, toY, toX, promoChar, + parseList[endPV - 1]); + else + parseList[endPV-1][0] = NULLCHAR; } while(valid); currentMove = endPV; if(currentMove == forwardMostMove) ClearPremoveHighlights(); else @@ -4753,16 +4888,19 @@ Boolean LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end) { int startPV; + char *p; if(index < 0 || index >= strlen(buf)) return FALSE; // sanity lastX = x; lastY = y; while(index > 0 && buf[index-1] != '\n') index--; // beginning of line startPV = index; - while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index; - index = startPV; - while(buf[index] && buf[index] != '\n') index++; + while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index; + if(index == startPV && (p = StrCaseStr(buf+index, "PV="))) startPV = p - buf + 3; + index = startPV; + do{ while(buf[index] && buf[index] != '\n') index++; + } while(buf[index] == '\n' && buf[index+1] == '\\' && buf[index+2] == ' ' && index++); // join kibitzed PV continuation line buf[index] = 0; - ParsePV(buf+startPV); + ParsePV(buf+startPV, FALSE); *start = startPV; *end = index-1; return TRUE; } @@ -4772,7 +4910,7 @@ 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. + ParsePV(lastPV[which], FALSE); // load the PV of the thinking engine in the boards array. return TRUE; } @@ -12544,9 +12682,9 @@ ToNrEvent(int to) } void -RevertEvent() +RevertEvent(Boolean annotate) { - if(PopTail(TRUE)) { // [HGM] vari: restore old game tail + if(PopTail(annotate)) { // [HGM] vari: restore old game tail return; } if (gameMode != IcsExamining) { @@ -14907,7 +15045,7 @@ PushTail(int firstMove, int lastMove) } storedGames++; - forwardMostMove = currentMove; // truncte game so we can start variation + forwardMostMove = firstMove; // truncate game so we can start variation if(storedGames == 1) GreyRevert(FALSE); } @@ -14919,6 +15057,7 @@ PopTail(Boolean annotate) if(appData.icsActive) return FALSE; // only in local mode if(!storedGames) return FALSE; // sanity + CommentPopDown(); // make sure no stale variation comments to the destroyed line can remain open storedGames--; ToNrEvent(savedFirst[storedGames]); // sets currentMove @@ -14932,11 +15071,12 @@ PopTail(Boolean annotate) sprintf(moveBuf, " %d. %s", i+2>>1, SavePart(parseList[i])); else sprintf(moveBuf, " %s", SavePart(parseList[i])); strcat(buf, moveBuf); + if(commentList[i]) { strcat(buf, " "); strcat(buf, commentList[i]); } if(!--cnt) { strcat(buf, "\n"); cnt = 10; } } strcat(buf, ")"); } - for(i=1; i 0 && --level == 0 && p-text > index && end == NULL) end = p-1; + } + if(*p == wait) wait = NULLCHAR; // closing ]} found + p++; + } + if(!start || !end) return; // no variation found, or syntax error in PGN: ignore click + if(appData.debugMode) fprintf(debugFP, "at move %d load variation '%s'\n", currentMove, start); + end[1] = NULLCHAR; // clip off comment beyond variation + ToNrEvent(currentMove-1); + PushTail(currentMove, forwardMostMove); // shelve main variation. This truncates game + // kludge: use ParsePV() to append variation to game + move = currentMove; + ParsePV(start, TRUE); + forwardMostMove = endPV; endPV = -1; currentMove = move; // cleanup what ParsePV did + ClearPremoveHighlights(); + CommentPopDown(); + ToNrEvent(currentMove+1); +}