char buf[MSG_SIZ];
int err, len;
+ ParseFeatures(appData.features[0], &first);
if(!appData.icsActive && !appData.noChessProgram && !appData.matchMode && // mode involves only first engine
!strcmp(appData.variant, "normal") && // no explicit variant request
appData.NrRanks == -1 && appData.NrFiles == -1 && appData.holdingsSize == -1 && // no size overrides requested
} else if (count == 0) {
RemoveInputSource(isr);
- DisplayFatalError(_("Connection closed by ICS"), 0, 0);
+ DisplayFatalError(_("Connection closed by ICS"), 0, 6666);
} else {
DisplayFatalError(_("Error reading from ICS"), error, 1);
}
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
+ 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',
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);
}
}
* 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
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);
{
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;
+ 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 == 'B') legal[r][f] = 4; else // request auto-promotion to victim
- if(*fen >= 'A' && *fen <= 'Z') legal[r][f] = 3; else
+ 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
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(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;
}
}
return;
}
- if(sscanf(message, "choice %s", promoRestrict) == 1) {
+ 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) {
void
ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
{
- ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; int p, rookX, oldEP, epRank, berolina = 0;
+ ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; int p, rookX, oldEP, epRank, epFile, berolina = 0;
int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1;
/* [HGM] compute & store e.p. status and castling rights for new position */
/* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */
if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;
- oldEP = (signed char)board[EP_FILE]; epRank = board[EP_RANK];
+ oldEP = (signed char)board[EP_FILE]; epRank = board[EP_RANK]; epFile = board[EP_FILE];
board[EP_STATUS] = EP_NONE;
board[EP_FILE] = board[EP_RANK] = 100;
}
pawn = board[fromY][fromX];
+ if(pieceDesc[pawn] && strchr(pieceDesc[pawn], 'e')) { // piece with user-defined e.p. capture
+ if(captured == EmptySquare && toX == epFile && (toY == (epRank & 127) || toY + (pawn < BlackPawn ? -1 : 1) == epRank - 128)) {
+ captured = board[epRank + (pawn < BlackPawn ? -1 : 1)][oldEP & berolina-1]; // remove victim
+ board[epRank + (pawn < BlackPawn ? -1 : 1)][oldEP & berolina-1] = EmptySquare;
+ pawn = EmptySquare; // kludge to suppress old e.p. code
+ }
+ }
if( pawn == WhiteLance || pawn == BlackLance ) {
if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu ) {
if(gameInfo.variant == VariantSpartan) board[EP_STATUS] = EP_PAWN_MOVE; // in Spartan no e.p. rights must be set
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
&& result != GameIsDrawn)
{ int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {
- int p = (signed char)boards[forwardMostMove][i][j] - color;
+ int p = (int)boards[forwardMostMove][i][j] - color;
if(p >= 0 && p <= (int)WhiteKing) k++;
oppoKings += (p + color == WhiteKing + BlackPawn - color);
}
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);
}
}
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);
}
}
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");
+ snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -ubt false");
}
if(!appData.useBitmaps || transparency[0]) {
- snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -lsc %s", Col2Text(2) ); // lightSquareColor
+ snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -lsc %s", Col2Text(2) ); // lightSquareColor
}
if(!appData.useBitmaps || transparency[1]) {
- snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -dsc %s", Col2Text(3) ); // darkSquareColor
+ 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");
+ snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -upf false");
if(appData.pieceDirectory[0]) {
- snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -pid \"%s\"", appData.pieceDirectory);
+ 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), MSG_SIZ-strlen(buf), " -trueColors %s", appData.trueColors ? "true" : "false");
+ snprintf(buf+strlen(buf), BUF_SIZ-strlen(buf), " -trueColors %s", appData.trueColors ? "true" : "false");
}
- if(!appData.pieceDirectory[0] && !appData.trueColors)
- snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -wpc %s -bpc %s",
+ 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);