extern char installDir[MSG_SIZ];
VariantClass startVariant; /* [HGM] nicks: initial variant */
Boolean abortMatch;
+int deadRanks;
extern int tinyLayout, smallLayout;
ChessProgramStats programStats;
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 */
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
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',
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);
}
}
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;
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;
!(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);
ChessSquare p = boards[0][rf][ff];
if(PieceToChar(p) == '+') gatingPiece = CHUDEMOTED(p); else
if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p); else
- if(p == WhiteKing || p == BlackKing || p == WhiteRook || p == BlackRook) {
+ if(p == WhiteKing || p == BlackKing || p == WhiteRook || p == BlackRook || p == WhitePawn || p == BlackPawn) {
int n = rightsBoard[toY][toX] ^= 1; // toggle virginity of K or R
DisplayMessage("", n ? _("rights granted") : _("rights revoked"));
gatingPiece = p;
}
- }
+ } else rightsBoard[toY][toX] = 0; // revoke rights on moving
boards[0][toY][toX] = boards[0][fromY][fromX];
- rightsBoard[toY][toX] = 0; // revoke rights on moving
if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings
if(boards[0][fromY][0] != EmptySquare) {
if(boards[0][fromY][1]) boards[0][fromY][1]--;
{
int r, f;
if(!appData.markers || !appData.highlightDragging) return;
- for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) legal[r][f] = 0;
- r=BOARD_HEIGHT-1; f=BOARD_LEFT;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) legal[r][f] = marker[r][f] = 0;
+ r=BOARD_HEIGHT-1-deadRanks; f=BOARD_LEFT;
while(*fen) {
int s = 0;
- marker[r][f] = 0;
if(*fen == 'M') legal[r][f] = 2; else // request promotion choice
- if(*fen >= '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
}
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;
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) {
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) {
!(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
}
// 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);
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;
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;
}
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
}
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
}
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
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
redraw, init, gameMode);
}
pieceDefs = FALSE; // [HGM] gen: reset engine-defined piece moves
+ deadRanks = 0; // assume entire board is used
for(i=0; i<EmptySquare; i++) { FREE(pieceDesc[i]); pieceDesc[i] = NULL; }
CleanupTail(); // [HGM] vari: delete any stored variations
CommentPopDown(); // [HGM] make sure no comments to the previous game keep hanging on
snprintf(buf, MSG_SIZ, " %d:%02d%c", seconds/60, seconds%60, 0);
}
+ if(appData.cumulativeTimePGN) {
+ snprintf(buf, MSG_SIZ, " %+ld", timeRemaining[i & 1][i+1]/1000);
+ }
+
snprintf( move_buffer, sizeof(move_buffer)/sizeof(move_buffer[0]),"{%s%.2f/%d%s}",
pvInfoList[i].score >= 0 ? "+" : "",
pvInfoList[i].score / 100.0,
startedFromSetupPosition = TRUE;
InitChessProgram(&first, FALSE);
if(fakeRights) { // [HGM] suppress this if we just pasted a FEN.
+ int r, f;
boards[0][EP_STATUS] = EP_NONE;
- boards[0][CASTLING][2] = boards[0][CASTLING][5] = BOARD_WIDTH>>1;
- if(boards[0][0][BOARD_WIDTH>>1] == king) {
- boards[0][CASTLING][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? BOARD_LEFT : NoRights;
- boards[0][CASTLING][0] = boards[0][0][BOARD_RGHT-1] == WhiteRook ? BOARD_RGHT-1 : NoRights;
- } else boards[0][CASTLING][2] = NoRights;
- if(boards[0][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == WHITE_TO_BLACK king) {
- boards[0][CASTLING][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? BOARD_LEFT : NoRights;
- boards[0][CASTLING][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : NoRights;
- } else boards[0][CASTLING][5] = NoRights;
- if(gameInfo.variant == VariantSChess) {
- int i;
- for(i=BOARD_LEFT; i<BOARD_RGHT; i++) { // pieces in their original position are assumed virgin
- boards[0][VIRGIN][i] = 0;
- if(boards[0][0][i] == FIDEArray[0][i-BOARD_LEFT]) boards[0][VIRGIN][i] |= VIRGIN_W;
- if(boards[0][BOARD_HEIGHT-1][i] == FIDEArray[1][i-BOARD_LEFT]) boards[0][VIRGIN][i] |= VIRGIN_B;
+ for(f=0; f<=nrCastlingRights; f++) boards[0][CASTLING][f] = NoRights;
+ for(r=BOARD_HEIGHT-1; r>=0; r--) for(f=BOARD_RGHT-1; f>=BOARD_LEFT; f--) { // first pass: Kings & e.p.
+ if(rightsBoard[r][f]) {
+ ChessSquare p = boards[0][r][f];
+ if(p == (blackPlaysFirst ? WhitePawn : BlackPawn)) boards[0][EP_STATUS] = f;
+ else if(p == king) boards[0][CASTLING][2] = f;
+ else if(p == WHITE_TO_BLACK king) boards[0][CASTLING][5] = f;
+ else rightsBoard[r][f] = 2; // mark for second pass
+ }
+ }
+ for(r=BOARD_HEIGHT-1; r>=0; r--) for(f=BOARD_RGHT-1; f>=BOARD_LEFT; f--) { // second pass: Rooks
+ if(rightsBoard[r][f] == 2) {
+ ChessSquare p = boards[0][r][f];
+ if(p == WhiteRook) boards[0][CASTLING][(f < boards[0][CASTLING][2])] = f; else
+ if(p == BlackRook) boards[0][CASTLING][(f < boards[0][CASTLING][5])+3] = f;
}
}
}
}
}
}
+ CopyBoard(rightsBoard, nullBoard);
if(gameMode != IcsExamining) { // [HGM] editpos: cycle trough boards
- int r;
+ int r, i;
for(r = 0; r < BOARD_HEIGHT; r++) {
for(x = BOARD_LEFT; x < BOARD_RGHT; x++) { // create 'menu board' by removing duplicates
ChessSquare p = menuBoard[r][x];
for(y = x + 1; y < BOARD_RGHT; y++) if(menuBoard[r][y] == p) menuBoard[r][y] = EmptySquare;
}
}
+ menuBoard[CASTLING][0] = menuBoard[CASTLING][3] = NoRights; // h-side Rook was deleted
DisplayMessage("Clicking clock again restores position", "");
if(gameInfo.variant != lastVariant) lastVariant = gameInfo.variant, CopyBoard(erasedBoard, boards[0]);
if(!nonEmpty) { // asked to clear an empty board
} else
CopyBoard(erasedBoard, currentBoard);
+ for(i=0; i<nrCastlingRights; i++) if(boards[0][CASTLING][i] != NoRights)
+ rightsBoard[castlingRank[i]][boards[0][CASTLING][i]] = 1; // copy remaining rights
}
}
if (gameMode == EditPosition) {
baseRank = 0;
case BlackRook:
if(y == baseRank && (x == BOARD_LEFT || x == BOARD_RGHT-1 || appData.fischerCastling)) hasRights = 1;
+ if(y == baseRank && (x == BOARD_WIDTH>>1 || appData.fischerCastling)) hasRights = 1;
goto defaultlabel;
case WhiteKing:
#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;
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;
}
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
((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;
}
{
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 */
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;
}
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++) {
p = fen;
+ for(i=1; i<=deadRanks; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) board[BOARD_HEIGHT-i][j] = DarkSquare;
+
/* Piece placement data */
- for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
+ for (i = BOARD_HEIGHT - 1 - deadRanks; i >= 0; i--) {
j = 0;
for (;;) {
if (*p == '/' || *p == ' ' || *p == '[' ) {
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;
{
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);