X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=b288d6bd5bd9b7c03cb14d2796130117b33f9acf;hb=5297eb5a91178cf9a403da89709a4661efde0210;hp=ac29d58ce1e23457decc8b57d6d788327a5b471b;hpb=c9b6cf0a2531f5b27357412aacf032c7969ae8c0;p=xboard.git diff --git a/backend.c b/backend.c index ac29d58..b288d6b 100644 --- a/backend.c +++ b/backend.c @@ -261,6 +261,7 @@ void ics_update_width P((int new_width)); extern char installDir[MSG_SIZ]; VariantClass startVariant; /* [HGM] nicks: initial variant */ Boolean abortMatch; +int deadRanks; extern int tinyLayout, smallLayout; ChessProgramStats programStats; @@ -564,8 +565,8 @@ ChessSquare KnightmateArray[2][BOARD_FILES] = { ChessSquare SpartanArray[2][BOARD_FILES] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, - { BlackAlfil, BlackMarshall, BlackKing, BlackDragon, - BlackDragon, BlackKing, BlackAngel, BlackAlfil } + { BlackAlfil, BlackDragon, BlackKing, BlackTower, + BlackTower, BlackKing, BlackAngel, BlackAlfil } }; ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */ @@ -691,18 +692,18 @@ ChessSquare CourierArray[2][BOARD_FILES] = { BlackFerz, BlackWazir, BlackBishop, BlackAlfil, BlackKnight, BlackRook } }; ChessSquare ChuArray[6][BOARD_FILES] = { - { WhiteLance, WhiteUnicorn, WhiteMan, WhiteFerz, WhiteWazir, WhiteKing, - WhiteAlfil, WhiteWazir, WhiteFerz, WhiteMan, WhiteUnicorn, WhiteLance }, - { BlackLance, BlackUnicorn, BlackMan, BlackFerz, BlackWazir, BlackAlfil, - BlackKing, BlackWazir, BlackFerz, BlackMan, BlackUnicorn, BlackLance }, - { WhiteCannon, EmptySquare, WhiteBishop, EmptySquare, WhiteNightrider, WhiteMarshall, - WhiteAngel, WhiteNightrider, EmptySquare, WhiteBishop, EmptySquare, WhiteCannon }, - { BlackCannon, EmptySquare, BlackBishop, EmptySquare, BlackNightrider, BlackAngel, - BlackMarshall, BlackNightrider, EmptySquare, BlackBishop, EmptySquare, BlackCannon }, - { WhiteFalcon, WhiteSilver, WhiteRook, WhiteCardinal, WhiteDragon, WhiteLion, - WhiteQueen, WhiteDragon, WhiteCardinal, WhiteRook, WhiteSilver, WhiteFalcon }, - { BlackFalcon, BlackSilver, BlackRook, BlackCardinal, BlackDragon, BlackQueen, - BlackLion, BlackDragon, BlackCardinal, BlackRook, BlackSilver, BlackFalcon } + { WhiteLance, WhiteCat, WhiteCopper, WhiteFerz, WhiteWazir, WhiteKing, + WhiteAlfil, WhiteWazir, WhiteFerz, WhiteCopper, WhiteCat, WhiteLance }, + { BlackLance, BlackCat, BlackCopper, BlackFerz, BlackWazir, BlackAlfil, + BlackKing, BlackWazir, BlackFerz, BlackCopper, BlackCat, BlackLance }, + { WhiteAxe, EmptySquare, WhiteBishop, EmptySquare, WhiteClaw, WhiteMarshall, + WhiteAngel, WhiteClaw, EmptySquare, WhiteBishop, EmptySquare, WhiteAxe }, + { BlackAxe, EmptySquare, BlackBishop, EmptySquare, BlackClaw, BlackAngel, + BlackMarshall, BlackClaw, EmptySquare, BlackBishop, EmptySquare, BlackAxe }, + { WhiteDagger, WhiteSword, WhiteRook, WhiteCardinal, WhiteDragon, WhiteLion, + WhiteQueen, WhiteDragon, WhiteCardinal, WhiteRook, WhiteSword, WhiteDagger }, + { BlackDagger, BlackSword, BlackRook, BlackCardinal, BlackDragon, BlackQueen, + BlackLion, BlackDragon, BlackCardinal, BlackRook, BlackSword, BlackDagger } }; #else // !(BOARD_FILES>=12) #define CourierArray CapablancaArray @@ -5162,14 +5163,14 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps) if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square char *m = moveList[moveNum]; static char c[2]; - *c = m[7]; // promoChar + *c = m[7]; if(*c == '\n') *c = NULLCHAR; // promoChar if((boards[moveNum][m[6]-ONE][m[5]-AAA] < BlackPawn) == (boards[moveNum][m[1]-ONE][m[0]-AAA] < BlackPawn)) // move is kludge to indicate castling snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", m[0], m[1] - '0', // convert to two moves m[2], m[3] - '0', m[5], m[6] - '0', m[2] + (m[0] > m[5] ? 1 : -1), m[3] - '0'); - else if(*c && m[8]) { // kill square followed by 2 characters: 2nd kill square rather than promo suffix - *c = m[9]; + else if(*c && m[8] != '\n') { // kill square followed by 2 characters: 2nd kill square rather than promo suffix + *c = m[9]; if(*c == '\n') *c = NULLCHAR; snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d,%c%d%c%d%s\n", m[0], m[1] - '0', // convert to three moves m[7], m[8] - '0', m[7], m[8] - '0', @@ -5385,7 +5386,7 @@ CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char sprintf(move, "%c%c%c%c%c\n", AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar); if(killX >= 0 && killY >= 0) { - sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY); + sprintf(move+4, ";%c%c%c\n", AAA + killX, ONE + killY, promoChar); if(kill2X >= 0 && kill2Y >= 0) sprintf(move+7, "%c%c%c\n", AAA + kill2X, ONE + kill2Y, promoChar); } } @@ -6280,8 +6281,10 @@ InitPosition (int redraw) gameInfo.boardWidth = 12; gameInfo.boardHeight = 12; nrCastlingRights = 0; - SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN.........^T..^L......^A^H/^F^G^M.^E^X^O^I.^P.^B^R..^D^S^C^VK" - "p.brqsexogcathd.vmlifn.........^t..^l......^a^h/^f^g^m.^e^x^o^i.^p.^b^r..^d^s^c^vk", SUFFIXES); +// SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN.........^T..^L......^A^H/^F^G^M.^E^X^O^I.^P.^B^R..^D^S^C^VK" + // "p.brqsexogcathd.vmlifn.........^t..^l......^a^h/^f^g^m.^e^x^o^i.^p.^b^r..^d^s^c^vk", SUFFIXES); + SetCharTableEsc(pieceToChar, "P.BRQSEXOG...HD..^DLI^HNV........^T..^L.C...A^AFT/^F^G^M.^E^X^O^I.^P.^B^R..M^S^C^VK" + "p.brqsexog...hd..^dli^hnv........^t..^l.c...a^aft/^f^g^m.^e^x^o^i.^p.^b^r..m^s^c^vk", SUFFIXES); break; case VariantCourier: pieces = CourierArray; @@ -6295,7 +6298,7 @@ InitPosition (int redraw) break; case VariantSpartan: pieces = SpartanArray; - SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k"); + SetCharTable(pieceToChar, "PNBRQ.....................K......lw......g...h......ck"); break; case VariantLion: pieces = lionArray; @@ -6495,7 +6498,7 @@ SendBoard (ChessProgramState *cps, int moveNum) * deprecated "black" command. */ if (!WhiteOnMove(moveNum)) // [HGM] but better a deprecated command than an illegal move... - SendToProgram(boards[0][1][BOARD_LEFT] == WhitePawn ? "a2a3\n" : "black\n", cps); + SendToProgram(boards[0][1][BOARD_LEFT] == WhitePawn && !pieceDesc[WhitePawn] ? "a2a3\n" : "black\nforce\n", cps); if(!cps->extendedEdit) left = BOARD_LEFT, right = BOARD_RGHT; // only board proper @@ -6699,9 +6702,12 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i !(fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0) ) // invalid move return FALSE; + if(legal[toY][toX] == 4) return FALSE; + piece = boards[currentMove][fromY][fromX]; if(gameInfo.variant == VariantChu) { promotionZoneSize = BOARD_HEIGHT/3; + if(legal[toY][toX] == 6) return FALSE; // no promotion if highlights deny it highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing; } else if(gameInfo.variant == VariantShogi) { promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8); @@ -7394,13 +7400,13 @@ MarkByFEN(char *fen) { int r, f; if(!appData.markers || !appData.highlightDragging) return; - for(r=0; r= 'A' && *fen <= 'Z') legal[r][f] = 3; else + if(*fen == 'B') legal[r][f] = 4; else // request auto-promotion to victim + if(*fen >= 'A' && *fen <= 'Z') legal[r][f] = 6; else if(*fen >= 'a' && *fen <= 'z') *fen += 'A' - 'a'; if(*fen == '/' && f > BOARD_LEFT) f = BOARD_LEFT, r--; else if(*fen == 'T') marker[r][f++] = 0; else @@ -7534,12 +7540,13 @@ void ReportClick(char *action, int x, int y) } Boolean right; // instructs front-end to use button-1 events as if they were button 3 +Boolean deferChoice; void LeftClick (ClickType clickType, int xPix, int yPix) { int x, y; - Boolean saveAnimate; + static Boolean saveAnimate; static int second = 0, promotionChoice = 0, clearFlag = 0, sweepSelecting = 0, flashing = 0, saveFlash; char promoChoice = NULLCHAR; ChessSquare piece; @@ -7547,6 +7554,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(flashing) return; + if(!deferChoice) { // when called for a retry, skip everything to the point where we left off x = EventToSquare(xPix, BOARD_WIDTH); y = EventToSquare(yPix, BOARD_HEIGHT); if (!flipView && y >= 0) { @@ -7637,7 +7645,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(gameMode == AnalyzeMode && (pausing || controlKey) && first.excludeMoves) { // use pause state to exclude moves doubleClick = TRUE; gatingPiece = boards[currentMove][y][x]; } - fromX = x; fromY = y; toX = toY = killX = killY = kill2X = kill2Y = -1; + fromX = x; fromY = y; toX = toY = killX = killY = kill2X = kill2Y = -1; *promoRestrict = NULLCHAR; 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 appData.sweepSelect && CanPromote(boards[currentMove][fromY][fromX], fromY) && originalY != y) { @@ -7689,7 +7697,7 @@ 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); - killX = killY = kill2X = kill2Y = -1; + killX = killY = kill2X = kill2Y = -1; *promoRestrict = NULLCHAR; 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 @@ -7890,12 +7898,25 @@ LeftClick (ClickType clickType, int xPix, int yPix) } // off-board moves should not be highlighted - if(x < 0 || y < 0) ClearHighlights(); - else ReportClick("put", x, y); + if(x < 0 || y < 0) { + ClearHighlights(); + DrawPosition(FALSE, NULL); + } else ReportClick("put", x, y); if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece)); - - if(legal[toY][toX] == 2) promoChoice = ToLower(PieceToChar(defaultPromoChoice)); // highlight-induced promotion + } + + if(legal[toY][toX] == 2) { // highlight-induced promotion + if(piece == defaultPromoChoice) promoChoice = NULLCHAR; // deferral + else promoChoice = ToLower(PieceToChar(defaultPromoChoice)); + } else if(legal[toY][toX] == 4) { // blue target square: engine must supply promotion choice + if(!*promoRestrict) { // but has not done that yet + deferChoice = TRUE; // set up retry for when it does + return; // and wait for that + } + promoChoice = ToLower(*promoRestrict); // force engine's choice + deferChoice = FALSE; + } if (legal[toY][toX] == 2 && !appData.sweepSelect || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) { SetHighlights(fromX, fromY, toX, toY); @@ -7913,6 +7934,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) DisplayMessage("Click in holdings to choose piece", ""); return; } + DrawPosition(FALSE, NULL); // shows piece on from-square during promo popup PromotionPopUp(promoChoice); } else { int oldMove = currentMove; @@ -7923,6 +7945,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed Explode(boards[currentMove-1], fromX, fromY, toX, toY)) DrawPosition(TRUE, boards[currentMove]); + else DrawPosition(FALSE, NULL); fromX = fromY = -1; flashing = 0; } @@ -9127,6 +9150,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h while(message[s] && message[s++] != ' '); if(BOARD_HEIGHT != h || BOARD_WIDTH != w + 4*(hand != 0) || gameInfo.holdingsSize != hand || dummy == 4 && gameInfo.variant != StringToVariant(varName) ) { // engine wants to change board format or variant + if(hand <= h) deadRanks = 0; else deadRanks = hand - h, h = hand; // adapt board to over-sized holdings appData.NrFiles = w; appData.NrRanks = h; appData.holdingsSize = hand; if(dummy == 4) gameInfo.variant = StringToVariant(varName); // parent variant InitPosition(1); // calls InitDrawingSizes to let new parameters take effect @@ -9143,10 +9167,10 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } if(sscanf(message, "piece %s %s", buf2, buf1) == 2) { ChessSquare piece = WhitePawn; - char *p=message+6, *q, *s = SUFFIXES, ID = *p; - if(*p == '+') piece = CHUPROMOTED(WhitePawn), ID = *++p; + char *p=message+6, *q, *s = SUFFIXES, ID = *p, promoted = 0; + if(*p == '+') promoted++, ID = *++p; if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++; - piece += CharToPiece(ID & 255) - WhitePawn; + piece = CharToPiece(ID & 255); if(promoted) piece = CHUPROMOTED(piece); if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR /* always accept definition of */ && piece != WhiteFalcon && piece != BlackFalcon /* wild-card pieces. */ && piece != WhiteCobra && piece != BlackCobra @@ -9162,9 +9186,13 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } return; } - if(sscanf(message, "choice %s", promoRestrict) == 1 && promoSweep != EmptySquare) { - promoSweep = CharToPiece(currentMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict)); - Sweep(0); + if(!appData.testLegality && sscanf(message, "choice %s", promoRestrict) == 1) { + if(deferChoice) { + LeftClick(Press, 0, 0); // finish the click that was interrupted + } else if(promoSweep != EmptySquare) { + promoSweep = CharToPiece(currentMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict)); + if(strlen(promoRestrict) > 1) Sweep(0); + } return; } /* [HGM] Allow engine to set up a position. Don't ask me why one would @@ -11187,7 +11215,7 @@ CreateTourney (char *name) int NamesToList (char *names, char **engineList, char **engineMnemonic, char *group) { - char buf[MSG_SIZ], *p, *q; + char buf[2*MSG_SIZ], *p, *q; int i=1, header, skip, all = !strcmp(group, "all"), depth = 0; insert = names; // afterwards, this global will point just after last retrieved engine line or group end in the 'names' skip = !all && group[0]; // if group requested, we start in skip mode @@ -11644,7 +11672,7 @@ GameEnds (ChessMove result, char *resultDetails, int whosays) && result != GameIsDrawn) { int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn); for(j=BOARD_LEFT; j= 0 && p <= (int)WhiteKing) k++; oppoKings += (p + color == WhiteKing + BlackPawn - color); } @@ -12012,6 +12040,7 @@ Reset (int redraw, int init) redraw, init, gameMode); } pieceDefs = FALSE; // [HGM] gen: reset engine-defined piece moves + deadRanks = 0; // assume entire board is used for(i=0; i= 0 ? "+" : "", pvInfoList[i].score / 100.0, @@ -14844,7 +14877,9 @@ MachineWhiteEvent () safeStrCpy(bookMove, "move ", sizeof(bookMove)/sizeof(bookMove[0])); strcat(bookMove, bookHit); - HandleMachineMove(bookMove, &first); + savedMessage = bookMove; // args for deferred call + savedState = &first; + ScheduleDelayedEvent(DeferredBookMove, 1); } } @@ -14919,7 +14954,9 @@ MachineBlackEvent () safeStrCpy(bookMove, "move ", sizeof(bookMove)/sizeof(bookMove[0])); strcat(bookMove, bookHit); - HandleMachineMove(bookMove, &first); + savedMessage = bookMove; // args for deferred call + savedState = &first; + ScheduleDelayedEvent(DeferredBookMove, 1); } } @@ -17803,11 +17840,13 @@ ResetClocks () #define FUDGE 25 /* 25ms = 1/40 sec; should be plenty even for 50 Hz clocks */ +static int timeSuffix; // [HGM] This should realy be a passed parameter, but it has to pass through too many levels for my laziness... + /* Decrement running clock by amount of time that has passed */ void DecrementClocks () { - long timeRemaining; + long tRemaining; long lastTickLength, fudge; TimeMark now; @@ -17824,28 +17863,32 @@ DecrementClocks () if (WhiteOnMove(forwardMostMove)) { if(whiteNPS >= 0) lastTickLength = 0; - timeRemaining = whiteTimeRemaining -= lastTickLength; - if(timeRemaining < 0 && !appData.icsActive) { + tRemaining = whiteTimeRemaining -= lastTickLength; + if( tRemaining < 0 && !appData.icsActive) { GetTimeQuota((forwardMostMove-whiteStartMove-1)/2, 0, whiteTC); // sets suddenDeath & nextSession; if(suddenDeath) { // [HGM] if we run out of a non-last incremental session, go to the next whiteStartMove = forwardMostMove; whiteTC = nextSession; - lastWhite= timeRemaining = whiteTimeRemaining += GetTimeQuota(-1, 0, whiteTC); + lastWhite= tRemaining = whiteTimeRemaining += GetTimeQuota(-1, 0, whiteTC); } } + if(forwardMostMove && appData.moveTime) timeSuffix = timeRemaining[0][forwardMostMove-1] - tRemaining; DisplayWhiteClock(whiteTimeRemaining - fudge, WhiteOnMove(currentMove < forwardMostMove ? currentMove : forwardMostMove)); + timeSuffix = 0; } else { if(blackNPS >= 0) lastTickLength = 0; - timeRemaining = blackTimeRemaining -= lastTickLength; - if(timeRemaining < 0 && !appData.icsActive) { // [HGM] if we run out of a non-last incremental session, go to the next + tRemaining = blackTimeRemaining -= lastTickLength; + if( tRemaining < 0 && !appData.icsActive) { // [HGM] if we run out of a non-last incremental session, go to the next GetTimeQuota((forwardMostMove-blackStartMove-1)/2, 0, blackTC); if(suddenDeath) { blackStartMove = forwardMostMove; - lastBlack = timeRemaining = blackTimeRemaining += GetTimeQuota(-1, 0, blackTC=nextSession); + lastBlack = tRemaining = blackTimeRemaining += GetTimeQuota(-1, 0, blackTC=nextSession); } } + if(forwardMostMove && appData.moveTime) timeSuffix = timeRemaining[1][forwardMostMove-1] - tRemaining; DisplayBlackClock(blackTimeRemaining - fudge, !WhiteOnMove(currentMove < forwardMostMove ? currentMove : forwardMostMove)); + timeSuffix = 0; } if (CheckFlags()) return; @@ -17860,7 +17903,7 @@ DecrementClocks () } tickStartTM = now; - intendedTickLength = NextTickLength(timeRemaining - fudge) + fudge; + intendedTickLength = NextTickLength( tRemaining - fudge) + fudge; StartClockTimer(intendedTickLength); /* if the time remaining has fallen below the alarm threshold, sound the @@ -17876,9 +17919,9 @@ DecrementClocks () ((gameMode == IcsPlayingBlack) && !WhiteOnMove(currentMove)) )) return; - if (alarmSounded && (timeRemaining > appData.icsAlarmTime)) { + if (alarmSounded && ( tRemaining > appData.icsAlarmTime)) { alarmSounded = FALSE; - } else if (!alarmSounded && (timeRemaining <= appData.icsAlarmTime)) { + } else if (!alarmSounded && ( tRemaining <= appData.icsAlarmTime)) { PlayAlarmSound(); alarmSounded = TRUE; } @@ -18019,7 +18062,7 @@ TimeString (long ms) { long second, minute, hour, day; char *sign = ""; - static char buf[32]; + static char buf[40], moveTime[8]; if (ms > 0 && ms <= 9900) { /* convert milliseconds to tenths, rounding up */ @@ -18046,13 +18089,16 @@ TimeString (long ms) minute = second / 60; second = second % 60; + if(timeSuffix) snprintf(moveTime, 8, " (%d)", timeSuffix/1000); // [HGM] kludge alert; fraction contains move time + else *moveTime = NULLCHAR; + if (day > 0) - snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%ld:%02ld:%02ld:%02ld ", - sign, day, hour, minute, second); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%ld:%02ld:%02ld:%02ld%s ", + sign, day, hour, minute, second, moveTime); else if (hour > 0) - snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%ld:%02ld:%02ld ", sign, hour, minute, second); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%ld:%02ld:%02ld%s ", sign, hour, minute, second, moveTime); else - snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%2ld:%02ld ", sign, minute, second); + snprintf(buf, sizeof(buf)/sizeof(buf[0]), " %s%2ld:%02ld%s ", sign, minute, second, moveTime); return buf; } @@ -18177,7 +18223,7 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) p = buf; /* Piece placement data */ - for (i = BOARD_HEIGHT - 1; i >= 0; i--) { + for (i = BOARD_HEIGHT - 1 - deadRanks; i >= 0; i--) { if(MSG_SIZ - (p - buf) < BOARD_RGHT - BOARD_LEFT + 20) { *p = 0; return StrSave(buf); } emptycount = 0; for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { @@ -18393,8 +18439,10 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) p = fen; + for(i=1; i<=deadRanks; i++) for(j=BOARD_LEFT; j= 0; i--) { + for (i = BOARD_HEIGHT - 1 - deadRanks; i >= 0; i--) { j = 0; for (;;) { if (*p == '/' || *p == ' ' || *p == '[' ) { @@ -19017,12 +19065,15 @@ LoadVariation (int index, char *text) ToNrEvent(currentMove+1); } +int transparency[2]; + void LoadTheme () { - char *p, *q, buf[MSG_SIZ]; +#define BUF_SIZ (2*MSG_SIZ) + char *p, *q, buf[BUF_SIZ]; if(engineLine && engineLine[0]) { // a theme was selected from the listbox - snprintf(buf, MSG_SIZ, "-theme %s", engineLine); + snprintf(buf, BUF_SIZ, "-theme %s", engineLine); ParseArgsFromString(buf); ActivateTheme(TRUE); // also redo colors return; @@ -19032,38 +19083,48 @@ LoadTheme () { int len; q = appData.themeNames; - snprintf(buf, MSG_SIZ, "\"%s\"", nickName); + snprintf(buf, BUF_SIZ, "\"%s\"", nickName); if(appData.useBitmaps) { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt true -lbtf \"%s\" -dbtf \"%s\" -lbtm %d -dbtm %d", - appData.liteBackTextureFile, appData.darkBackTextureFile, + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ubt true -lbtf \"%s\"", + Shorten(appData.liteBackTextureFile)); + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -dbtf \"%s\" -lbtm %d -dbtm %d", + Shorten(appData.darkBackTextureFile), appData.liteBackTextureMode, appData.darkBackTextureMode ); } else { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt false -lsc %s -dsc %s", - Col2Text(2), // lightSquareColor - Col2Text(3) ); // darkSquareColor + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ubt false"); + } + if(!appData.useBitmaps || transparency[0]) { + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -lsc %s", Col2Text(2) ); // lightSquareColor + } + if(!appData.useBitmaps || transparency[1]) { + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -dsc %s", Col2Text(3) ); // darkSquareColor } if(appData.useBorder) { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub true -border \"%s\"", + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ub true -border \"%s\"", appData.border); } else { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub false"); + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ub false"); } if(appData.useFont) { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf true -pf \"%s\" -fptc \"%s\" -fpfcw %s -fpbcb %s", + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -upf true -pf \"%s\" -fptc \"%s\" -fpfcw %s -fpbcb %s", appData.renderPiecesWithFont, appData.fontToPieceTable, Col2Text(9), // appData.fontBackColorWhite Col2Text(10) ); // appData.fontForeColorBlack } else { - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf false -pid \"%s\"", - appData.pieceDirectory); - if(!appData.pieceDirectory[0]) - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -wpc %s -bpc %s", + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -upf false"); + if(appData.pieceDirectory[0]) { + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -pid \"%s\"", Shorten(appData.pieceDirectory)); + if(appData.trueColors != 2) // 2 is a kludge to suppress this in WinBoard + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -trueColors %s", appData.trueColors ? "true" : "false"); + } + if(!appData.pieceDirectory[0] || !appData.trueColors) + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -wpc %s -bpc %s", Col2Text(0), // whitePieceColor Col2Text(1) ); // blackPieceColor } - snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -hsc %s -phc %s\n", + snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -hsc %s -phc %s\n", Col2Text(4), // highlightSquareColor Col2Text(5) ); // premoveHighlightColor appData.themeNames = malloc(len = strlen(q) + strlen(buf) + 1);