void
Load (ChessProgramState *cps, int i)
{
- char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ];
+ char *p, *q, buf[MSG_SIZ], command[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ], jar;
if(engineLine && engineLine[0]) { // an engine was selected from the combo box
snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
p[-1] = SLASH;
if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split!
} else { ASSIGN(appData.directory[i], "."); }
+ jar = (strstr(p, ".jar") == p + strlen(p) - 4);
if(params[0]) {
if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces
snprintf(command, MSG_SIZ, "%s %s", p, params);
p = command;
}
+ if(jar) { snprintf(buf3, MSG_SIZ, "java -jar %s", p); p = buf3; }
ASSIGN(appData.chessProgram[i], p);
appData.isUCI[i] = isUCI;
appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
NextTourneyGame(-1, &dummy);
ReserveGame(-1, 0);
if(nextGame <= appData.matchGames) {
- DisplayNote(_("You restarted an already completed tourney\nOne more cycle will now be added to it\nGames commence in 10 sec"));
+ DisplayNote(_("You restarted an already completed tourney.\nOne more cycle will now be added to it.\nGames commence in 10 sec."));
matchMode = mode;
ScheduleDelayedEvent(NextMatchGame, 10000);
return;
return retbuf;
}
+char engineVariant[MSG_SIZ];
char *variantNames[] = VARIANT_NAMES;
char *
VariantName (VariantClass v)
{
+ if(v == VariantUnknown || *engineVariant) return engineVariant;
return variantNames[v];
}
} else {
char tmp[MSG_SIZ];
if(gameMode == IcsObserving) // restore original ICS messages
+ /* TRANSLATORS: to 'kibitz' is to send a message to all players and the game observers */
snprintf(tmp, MSG_SIZ, "%s kibitzes: %s", star_match[0], parse);
else
+ /* TRANSLATORS: to 'kibitz' is to send a message to all players and the game observers */
snprintf(tmp, MSG_SIZ, _("your opponent kibitzes: %s"), parse);
SendToPlayer(tmp, strlen(tmp));
}
}
-static int lastX, lastY, selectFlag, dragging;
+static int lastX, lastY, lastLeftX, lastLeftY, selectFlag, dragging;
+static ClickType lastClickType;
void
Sweep (int step)
prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
if (clickType == Press) ErrorPopDown();
+ lastClickType = clickType, lastLeftX = xPix, lastLeftY = yPix; // [HGM] alien: remember state
x = EventToSquare(xPix, BOARD_WIDTH);
y = EventToSquare(yPix, BOARD_HEIGHT);
}
if (!strncmp(message, "setup ", 6) &&
- (!appData.testLegality || gameInfo.variant == VariantFairy || NonStandardBoardSize())
+ (!appData.testLegality || gameInfo.variant == VariantFairy || gameInfo.variant == VariantUnknown || NonStandardBoardSize())
) { // [HGM] allow first engine to define opening position
- int dummy, s=6; char buf[MSG_SIZ];
+ int dummy, w, h, hand, s=6; char buf[MSG_SIZ], varName[MSG_SIZ];
if(appData.icsActive || forwardMostMove != 0 || cps != &first) return;
+ *buf = NULLCHAR;
if(sscanf(message, "setup (%s", buf) == 1) s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf);
if(startedFromSetupPosition) return;
- if(sscanf(message+s, "%dx%d+%d", &dummy, &dummy, &dummy) == 3) while(message[s] && message[s++] != ' '); // for compatibility with Alien Edition
+ dummy = sscanf(message+s, "%dx%d+%d_%s", &w, &h, &hand, varName);
+ if(dummy >= 3) {
+ 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
+ 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(*buf) SetCharTable(pieceToChar, buf); // do again, for it was spoiled by InitPosition
+ }
+ }
ParseFEN(boards[0], &dummy, message+s);
DrawPosition(TRUE, boards[0]);
startedFromSetupPosition = TRUE;
MarkByFEN(message+10); // [HGM] alien: allow engine to mark board squares
return;
}
+ if(!strncmp(message, "click ", 6)) {
+ char f, c=0; int x, y; // [HGM] alien: allow engine to finish user moves (i.e. engine-driven one-click moving)
+ if(appData.testLegality || !appData.oneClick) return;
+ sscanf(message+6, "%c%d%c", &f, &y, &c);
+ x = f - 'a' + BOARD_LEFT, y -= ONE - '0';
+ if(flipView) x = BOARD_WIDTH-1 - x; else y = BOARD_HEIGHT-1 - y;
+ x = x*squareSize + (x+1)*lineGap + squareSize/2;
+ y = y*squareSize + (y+1)*lineGap + squareSize/2;
+ f = first.highlight; first.highlight = 0; // kludge to suppress lift/put in response to own clicks
+ if(lastClickType == Press) // if button still down, fake release on same square, to be ready for next click
+ LeftClick(Release, lastLeftX, lastLeftY);
+ controlKey = (c == ',');
+ LeftClick(Press, x, y);
+ LeftClick(Release, x, y);
+ first.highlight = f;
+ return;
+ }
/*
* If the move is illegal, cancel it and redraw the board.
* Also deal with other error cases. Matching is rather loose
DisplayInformation(_("Machine accepts your draw offer"));
GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD);
} else {
- DisplayInformation(_("Machine offers a draw\nSelect Action / Draw to agree"));
+ DisplayInformation(_("Machine offers a draw.\nSelect Action / Draw to accept."));
}
}
}
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
+ /* TRANSLATORS: PV = principal variation, the variation the chess engine thinks is the best for everyone */
+ DisplayError(_("failed writing PV"), 0);
}
tempStats.depth = plylev;
{
/* [HGM] Awkward testing. Should really be a table */
int overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;
+ if( gameInfo.variant == VariantUnknown || *engineVariant) return 0; // engine-defined name never needs prefix
if( gameInfo.variant == VariantXiangqi )
overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 10 || gameInfo.holdingsSize != 0;
if( gameInfo.variant == VariantShogi )
lastHint[0] = NULLCHAR;
ClearGameInfo(&gameInfo);
gameInfo.variant = StringToVariant(appData.variant);
+ if(gameInfo.variant == VariantNormal && strcmp(appData.variant, "normal")) gameInfo.variant = VariantUnknown;
ics_user_moved = ics_clock_paused = FALSE;
ics_getting_history = H_FALSE;
ics_gamenum = -1;
AnalyzeFileEvent();
}
+ if(gameInfo.result == GameUnfinished && gameInfo.resultDetails && appData.clockMode) {
+ long int w, b; // [HGM] adjourn: restore saved clock times
+ char *p = strstr(gameInfo.resultDetails, "(Clocks:");
+ if(p && sscanf(p+8, "%ld,%ld", &w, &b) == 2) {
+ timeRemaining[0][forwardMostMove] = whiteTimeRemaining = 1000*w + 500;
+ timeRemaining[1][forwardMostMove] = blackTimeRemaining = 1000*b + 500;
+ }
+ }
+
if(creatingBook) return TRUE;
if (!matchMode && pos > 0) {
ToNrEvent(pos); // [HGM] no autoplay if selected on position
/* Print result */
if (gameInfo.resultDetails != NULL &&
gameInfo.resultDetails[0] != NULLCHAR) {
- fprintf(f, "{%s} %s\n\n", gameInfo.resultDetails,
- PGNResult(gameInfo.result));
+ char buf[MSG_SIZ], *p = gameInfo.resultDetails;
+ if(gameInfo.result == GameUnfinished && appData.clockMode &&
+ (gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack || gameMode == TwoMachinesPlay)) // [HGM] adjourn: save clock settings
+ snprintf(buf, MSG_SIZ, "%s (Clocks: %ld, %ld)", p, whiteTimeRemaining/1000, blackTimeRemaining/1000), p = buf;
+ fprintf(f, "{%s} %s\n\n", p, PGNResult(gameInfo.result));
} else {
fprintf(f, "%s\n\n", PGNResult(gameInfo.result));
}
case MachinePlaysWhite:
case MachinePlaysBlack:
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {
- DisplayError(_("Wait until your turn,\nor select Move Now"), 0);
+ DisplayError(_("Wait until your turn,\nor select 'Move Now'."), 0);
return;
}
/* fall through */
case MachinePlaysWhite:
case MachinePlaysBlack:
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {
- DisplayError(_("Wait until your turn,\nor select Move Now"), 0);
+ DisplayError(_("Wait until your turn,\nor select 'Move Now'."), 0);
return;
}
if (forwardMostMove < 2) return;
switch (gameMode) {
case MachinePlaysWhite:
if (WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
case BeginningOfGame:
case MachinePlaysBlack:
if (!WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
switch (gameMode) {
case MachinePlaysWhite:
if (WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
case BeginningOfGame:
case MachinePlaysBlack:
if (!WhiteOnMove(forwardMostMove)) {
- DisplayError(_("Wait until your turn"), 0);
+ DisplayError(_("Wait until your turn."), 0);
return;
}
break;
SendToProgram(message, cps);
}
+char *
+EngineDefinedVariant (ChessProgramState *cps, int n)
+{ // return name of n-th unknown variant that engine supports
+ static char buf[MSG_SIZ];
+ char *p, *s = cps->variants;
+ if(!s) return NULL;
+ do { // parse string from variants feature
+ VariantClass v;
+ p = strchr(s, ',');
+ if(p) *p = NULLCHAR;
+ v = StringToVariant(s);
+ if(v == VariantNormal && strcmp(s, "normal") && !strstr(s, "_normal")) v = VariantUnknown; // garbage is recognized as normal
+ if(v == VariantUnknown) { // non-standard variant in list of engine-supported variants
+ if(--n < 0) safeStrCpy(buf, s, MSG_SIZ);
+ }
+ if(p) *p++ = ',';
+ if(n < 0) return buf;
+ } while(s = p);
+ return NULL;
+}
+
int
BoolFeature (char **p, char *name, int *loc, ChessProgramState *cps)
{
*p++ = '+';
piece = (ChessSquare)(DEMOTED piece);
}
- *p++ = PieceToChar(piece);
+ *p++ = (piece == DarkSquare ? '*' : PieceToChar(piece));
if(p[-1] == '~') {
/* [HGM] flag promoted pieces as '<promoted>~' (Crazyhouse) */
p[-1] = PieceToChar((ChessSquare)(DEMOTED piece));
while (emptycount--)
board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;
#endif
+ } else if (*p == '*') {
+ board[i][(j++)+gameInfo.holdingsWidth] = DarkSquare; p++;
} else if (isdigit(*p)) {
emptycount = *p++ - '0';
while(isdigit(*p)) emptycount = 10*emptycount + *p++ - '0'; /* [HGM] allow > 9 */