#endif
-/* A point in time */
-typedef struct {
- long sec; /* Assuming this is >= 32 bits */
- int ms; /* Assuming this is >= 16 bits */
-} TimeMark;
-
int establish P((void));
void read_from_player P((InputSourceRef isr, VOIDSTAR closure,
char *buf, int count, int error));
char *SavePart P((char *));
int SaveGameOldStyle P((FILE *));
int SaveGamePGN P((FILE *));
-void GetTimeMark P((TimeMark *));
-long SubtractTimeMarks P((TimeMark *, TimeMark *));
int CheckFlags P((void));
long NextTickLength P((long));
void CheckTimeControl P((void));
len = snprintf(buf, MSG_SIZ, _("protocol version %d not supported"),
appData.protocolVersion[n]);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "InitBackEnd1: buffer truncated.\n");
DisplayFatalError(buf, 0, 2);
}
InitEngineUCI( installDir, cps ); // [HGM] moved here from winboard.c, to make available in xboard
+ ParseFeatures(appData.featureDefaults, cps);
}
ChessProgramState *savCps;
case VariantKriegspiel: /* need to hide pieces and move details */
/* case VariantFischeRandom: (Fabien: moved below) */
len = snprintf(buf,MSG_SIZ, _("Variant %s supported only in ICS mode"), appData.variant);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "InitBackEnd1: buffer truncated.\n");
DisplayFatalError(buf, 0, 2);
case Variant36:
default:
len = snprintf(buf, MSG_SIZ, _("Unknown variant name %s"), appData.variant);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "InitBackEnd1: buffer truncated.\n");
DisplayFatalError(buf, 0, 2);
len = snprintf(buf, MSG_SIZ, _("Could not connect to host %s, port %s"),
appData.icsHost, appData.icsPort);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "InitBackEnd3: buffer truncated.\n");
DisplayFatalError(buf, err, 1);
initialMode = Training;
} else {
len = snprintf(buf, MSG_SIZ, _("Unknown initialMode %s"), appData.initialMode);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "InitBackEnd3: buffer truncated.\n");
DisplayFatalError(buf, 0, 2);
break;
default:
len = snprintf(buf, MSG_SIZ, _("Unknown wild type %d"), wnum);
- if( (len > MSG_SIZ) && appData.debugMode )
+ if( (len >= MSG_SIZ) && appData.debugMode )
fprintf(debugFP, "StringToVariant: buffer truncated.\n");
DisplayError(buf, 0);
flipView = appData.flipView;
DrawPosition(TRUE, boards[currentMove]);
DisplayBothClocks();
- snprintf(str, MSG_SIZ, "%s vs. %s",
+ snprintf(str, MSG_SIZ, _("%s vs. %s"),
gameInfo.white, gameInfo.black);
DisplayTitle(str);
gameMode = IcsIdle;
strncmp(why, "Continuing ", 11) == 0) {
gs_gamenum = gamenum;
safeStrCpy(gs_kind, strchr(why, ' ') + 1,sizeof(gs_kind)/sizeof(gs_kind[0]));
+ if(ics_gamenum == -1) // [HGM] only if we are not already involved in a game (because gin=1 sends us such messages)
VariantSwitch(boards[currentMove], StringToVariant(gs_kind)); // [HGM] variantswitch: even before we get first board
#if ZIPPY
if (appData.zippyPlay) {
char wh[16], bh[16];
PackHolding(wh, white_holding);
PackHolding(bh, black_holding);
- snprintf(str, MSG_SIZ,"[%s-%s] %s-%s", wh, bh,
+ snprintf(str, MSG_SIZ, "[%s-%s] %s-%s", wh, bh,
gameInfo.white, gameInfo.black);
} else {
- snprintf(str, MSG_SIZ, "%s [%s] vs. %s [%s]",
+ snprintf(str, MSG_SIZ, _("%s [%s] vs. %s [%s]"),
gameInfo.white, white_holding,
gameInfo.black, black_holding);
}
board[k][1] = board[k][BOARD_WIDTH-2] = (ChessSquare) 0;;
}
}
+ if(moveNum==0 && gameInfo.variant == VariantSChess) {
+ board[5][BOARD_RGHT+1] = WhiteAngel;
+ board[6][BOARD_RGHT+1] = WhiteMarshall;
+ board[1][0] = BlackMarshall;
+ board[2][0] = BlackAngel;
+ board[1][1] = board[2][1] = board[5][BOARD_RGHT] = board[6][BOARD_RGHT] = 1;
+ }
CopyBoard(boards[moveNum], board);
boards[moveNum][HOLDINGS_SET] = 0; // [HGM] indicate holdings not set
if (moveNum == 0) {
if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;
initialRights[4] = boards[moveNum][CASTLING][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? NoRights : j);
+ boards[moveNum][CASTLING][2] = boards[moveNum][CASTLING][5] = NoRights;
if(gameInfo.variant == VariantKnightmate) { wKing = WhiteUnicorn; bKing = BlackUnicorn; }
for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
if(board[0][k] == wKing) initialRights[2] = boards[moveNum][CASTLING][2] = k;
basetime, increment, (int) gameInfo.variant);
} else {
if(gameInfo.variant == VariantNormal)
- snprintf(str, MSG_SIZ, "%s (%d) vs. %s (%d) {%d %d}",
+ snprintf(str, MSG_SIZ, _("%s (%d) vs. %s (%d) {%d %d}"),
gameInfo.white, white_stren, gameInfo.black, black_stren,
basetime, increment);
else
- snprintf(str, MSG_SIZ, "%s (%d) vs. %s (%d) {%d %d %s}",
+ snprintf(str, MSG_SIZ, _("%s (%d) vs. %s (%d) {%d %d %s}"),
gameInfo.white, white_stren, gameInfo.black, black_stren,
basetime, increment, VariantName(gameInfo.variant));
}
char promoChar;
{
char user_move[MSG_SIZ];
+ char suffix[4];
+
+ if(gameInfo.variant == VariantSChess && promoChar) {
+ snprintf(suffix, 4, "=%c", toX == BOARD_WIDTH<<1 ? ToUpper(promoChar) : ToLower(promoChar));
+ if(moveType == NormalMove) moveType = WhitePromotion; // kludge to do gating
+ } else suffix[0] = NULLCHAR;
switch (moveType) {
default:
case WhiteHSideCastleFR:
case BlackHSideCastleFR:
/* POP Fabien */
- snprintf(user_move, MSG_SIZ, "o-o\n");
+ snprintf(user_move, MSG_SIZ, "o-o%s\n", suffix);
break;
case WhiteQueenSideCastle:
case BlackQueenSideCastle:
case WhiteASideCastleFR:
case BlackASideCastleFR:
/* POP Fabien */
- snprintf(user_move, MSG_SIZ, "o-o-o\n");
+ snprintf(user_move, MSG_SIZ, "o-o-o%s\n",suffix);
break;
case WhiteNonPromotion:
case BlackNonPromotion:
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;
+ 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;
else if((int)promoSweep == -1) promoSweep = WhiteKing;
else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn;
else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
- if(!step) step = 1;
+ if(!step) step = -1;
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
appData.testLegality && (promoSweep == king ||
gameInfo.variant == VariantShogi && promoSweep != PROMOTED last && last != PROMOTED promoSweep && last != promoSweep));
} else {
ChessSquare *bp;
- int i, j;
+ int i, j, left=0, right=BOARD_WIDTH;
/* Kludge to set black to move, avoiding the troublesome and now
* 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);
+ if(!cps->extendedEdit) left = BOARD_LEFT, right = BOARD_RGHT; // only board proper
+
SendToProgram("edit\n", cps);
SendToProgram("#\n", cps);
for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
- bp = &boards[moveNum][i][BOARD_LEFT];
- for (j = BOARD_LEFT; j < BOARD_RGHT; j++, bp++) {
+ bp = &boards[moveNum][i][left];
+ for (j = left; j < right; j++, bp++) {
+ if(j == BOARD_LEFT-1 || j == BOARD_RGHT) continue;
if ((int) *bp < (int) BlackPawn) {
- snprintf(message, MSG_SIZ, "%c%c%c\n", PieceToChar(*bp),
- AAA + j, ONE + i);
+ if(j == BOARD_RGHT+1)
+ snprintf(message, MSG_SIZ, "%c@%d\n", PieceToChar(*bp), bp[-1]);
+ else snprintf(message, MSG_SIZ, "%c%c%c\n", PieceToChar(*bp), AAA + j, ONE + i);
if(message[0] == '+' || message[0] == '~') {
snprintf(message, MSG_SIZ,"%c%c%c+\n",
PieceToChar((ChessSquare)(DEMOTED *bp)),
SendToProgram("c\n", cps);
for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
- bp = &boards[moveNum][i][BOARD_LEFT];
- for (j = BOARD_LEFT; j < BOARD_RGHT; j++, bp++) {
+ bp = &boards[moveNum][i][left];
+ for (j = left; j < right; j++, bp++) {
+ if(j == BOARD_LEFT-1 || j == BOARD_RGHT) continue;
if (((int) *bp != (int) EmptySquare)
&& ((int) *bp >= (int) BlackPawn)) {
- snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
+ if(j == BOARD_LEFT-2)
+ snprintf(message, MSG_SIZ, "%c@%d\n", ToUpper(PieceToChar(*bp)), bp[1]);
+ else snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
AAA + j, ONE + i);
if(message[0] == '+' || message[0] == '~') {
snprintf(message, MSG_SIZ,"%c%c%c+\n",
gameMode = MachinePlaysBlack;
StartClocks();
SetGameInfo();
- snprintf(buf, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);
+ snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
DisplayTitle(buf);
if (first.sendName) {
snprintf(buf, MSG_SIZ,"name %s\n", gameInfo.white);
hisPerpetual = PerpetualChase(k, forwardMostMove);
ourPerpetual = PerpetualChase(k+1, forwardMostMove);
if(ourPerpetual && !hisPerpetual) { // we are actively chasing him: forfeit
+ static char resdet[MSG_SIZ];
result = WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins;
- details = "Xboard adjudication: perpetual chasing";
+ details = resdet;
+ snprintf(resdet, MSG_SIZ, "Xboard adjudication: perpetual chasing of %c%c", ourPerpetual>>8, ourPerpetual&255);
} else
if(hisPerpetual && !ourPerpetual) // he is chasing us, but did not repeat yet
break; // Abort repetition-checking loop.
return; // [HGM] This return was missing, causing option features to be recognized as non-compliant commands!
}
- if (!appData.testLegality && !strncmp(message, "setup ", 6)) { // [HGM] allow first engine to define opening position
+ if ((!appData.testLegality || gameInfo.variant == VariantFairy) &&
+ !strncmp(message, "setup ", 6)) { // [HGM] allow first engine to define opening position
int dummy, s=6; char buf[MSG_SIZ];
- if(appData.icsActive || forwardMostMove != 0 || cps != &first || startedFromSetupPosition) return;
+ if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
+ if(startedFromSetupPosition) return;
ParseFEN(boards[0], &dummy, message+s);
DrawPosition(TRUE, boards[0]);
startedFromSetupPosition = TRUE;
parseList[currentMove], _(cps->which));
DisplayMoveError(buf1);
DrawPosition(FALSE, boards[currentMove]);
+
+ SetUserThinkingEnables();
return;
}
if (strncmp(message, "time", 4) == 0 && StrStr(message, "Illegal")) {
if(f = fopen(buf, "w")) { // export PV to applicable PV file
fprintf(f, "%5.2f/%-2d %s", curscore/100., plylev, pv);
fclose(f);
- } else DisplayError("failed writing PV", 0);
+ } else DisplayError(_("failed writing PV"), 0);
}
tempStats.depth = plylev;
hintRequested = FALSE;
bookRequested = FALSE;
+ ParseFeatures(appData.features[cps == &second], cps); // [HGM] allow user to overrule features
/* [HGM] some new WB protocol commands to configure engine are sent now, if engine supports them */
/* moved to before sending initstring in 4.3.15, so Polyglot can delay UCI 'isready' to recepton of 'new' */
if(cps->memSize) { /* [HGM] memory */
SWAP(logo, p)
SWAP(pgnName, p)
SWAP(pvSAN, h)
+ SWAP(engOptions, p)
}
void
first.matchWins, second.matchWins,
appData.matchGames - (first.matchWins + second.matchWins));
if(!appData.tourneyFile[0]) matchGame++, DisplayTwoMachinesTitle(); // [HGM] update result in window title
+ if(strcmp(ranking, "busy") && appData.afterTourney && appData.afterTourney[0]) RunCommand(appData.afterTourney);
popupRequested++; // [HGM] crash: postpone to after resetting endingGame
if (appData.firstPlaysBlack) { // [HGM] match: back to original for next match
first.twoMachinesColor = "black\n";
for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
if(board[r][f] != pieceType[quickBoard[(r<<4)+f]]) return FALSE;
}
- return TRUE;
+ break;
case 2: // can have extra material on empty squares
for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
if(board[r][f] == EmptySquare) continue;
if(board[r][f] != pieceType[quickBoard[(r<<4)+f]]) return FALSE;
}
- return TRUE;
+ break;
case 3: // material with exact Pawn structure
for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++) {
if(board[r][f] != WhitePawn && board[r][f] != BlackPawn) continue;
} // fall through to material comparison
case 4: // exact material
for(r=0; r<EmptySquare; r++) if(counts[r] != maxCounts[r]) return FALSE;
- return TRUE;
+ break;
case 6: // material range with given imbalance
for(r=0; r<BlackPawn; r++) if(counts[r] - minCounts[r] != counts[r+BlackPawn] - minCounts[r+BlackPawn]) return FALSE;
// fall through to range comparison
case 5: // material range
for(r=0; r<EmptySquare; r++) if(counts[r] < minCounts[r] || counts[r] > maxCounts[r]) return FALSE;
- return TRUE;
}
+ return TRUE;
}
int QuickScan(Board board, Move *move)
fromY = DROP_RANK;
toX = currentMoveString[2] - AAA;
toY = currentMoveString[3] - ONE;
+ promoChar = 0;
break;
}
// Move encountered; peform it. We need to shuttle between two boards, as even/odd index determines side to move
yynewfile(f);
if (lg && lg->gameInfo.white && lg->gameInfo.black) {
- snprintf(buf, sizeof(buf), "%s vs. %s", lg->gameInfo.white,
+ snprintf(buf, sizeof(buf), _("%s vs. %s"), lg->gameInfo.white,
lg->gameInfo.black);
DisplayTitle(buf);
} else if (*title != NULLCHAR) {
DisplayMessage(_("Waiting for access to save file"), "");
flock(fileno(f), LOCK_EX); // [HGM] lock: lock file while we are writing
DisplayMessage(_("Saving game"), "");
- if(lseek(fileno(f), 0, SEEK_END) == -1) DisplayError("Bad Seek", errno); // better safe than sorry...
+ if(lseek(fileno(f), 0, SEEK_END) == -1) DisplayError(_("Bad Seek"), errno); // better safe than sorry...
result = SaveGame(f, 0, NULL);
DisplayMessage(buf, "");
return result;
pausing = FALSE;
ModeHighlight();
SetGameInfo();
- snprintf(buf, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);
+ snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
DisplayTitle(buf);
if (first.sendName) {
snprintf(buf, MSG_SIZ, "name %s\n", gameInfo.black);
pausing = FALSE;
ModeHighlight();
SetGameInfo();
- snprintf(buf, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);
+ snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
DisplayTitle(buf);
if (first.sendName) {
snprintf(buf, MSG_SIZ, "name %s\n", gameInfo.white);
char buf[MSG_SIZ];
if (appData.matchGames > 0) {
if(appData.tourneyFile[0]) {
- snprintf(buf, MSG_SIZ, "%s vs. %s (%d/%d%s)",
+ snprintf(buf, MSG_SIZ, _("%s vs. %s (%d/%d%s)"),
gameInfo.white, gameInfo.black,
nextGame+1, appData.matchGames+1,
appData.tourneyType>0 ? "gt" : appData.tourneyType<0 ? "sw" : "rr");
} else
if (first.twoMachinesColor[0] == 'w') {
- snprintf(buf, MSG_SIZ, "%s vs. %s (%d-%d-%d)",
+ snprintf(buf, MSG_SIZ, _("%s vs. %s (%d-%d-%d)"),
gameInfo.white, gameInfo.black,
first.matchWins, second.matchWins,
matchGame - 1 - (first.matchWins + second.matchWins));
} else {
- snprintf(buf, MSG_SIZ, "%s vs. %s (%d-%d-%d)",
+ snprintf(buf, MSG_SIZ, _("%s vs. %s (%d-%d-%d)"),
gameInfo.white, gameInfo.black,
second.matchWins, first.matchWins,
matchGame - 1 - (first.matchWins + second.matchWins));
}
} else {
- snprintf(buf, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);
+ snprintf(buf, MSG_SIZ, _("%s vs. %s"), gameInfo.white, gameInfo.black);
}
DisplayTitle(buf);
}
if (gameMode == EditPosition)
return;
+ MarkTargetSquares(1);
+
if (gameMode == PlayFromGameFile && !pausing)
PauseEvent();
target, currentMove, forwardMostMove);
if (gameMode == EditPosition) return;
+ MarkTargetSquares(1);
if (currentMove <= backwardMostMove) {
ClearHighlights();
DrawPosition(full_redraw, boards[currentMove]);
if (*p == NULLCHAR) return;
if (BoolFeature(&p, "setboard", &cps->useSetboard, cps)) continue;
+ if (BoolFeature(&p, "xedit", &cps->extendedEdit, cps)) continue;
if (BoolFeature(&p, "time", &cps->sendTime, cps)) continue;
if (BoolFeature(&p, "draw", &cps->sendDrawOffers, cps)) continue;
if (BoolFeature(&p, "sigint", &cps->useSigint, cps)) continue;