char white_holding[64], black_holding[64];
TimeMark lastNodeCountTime;
long lastNodeCount=0;
-int shiftKey; // [HGM] set by mouse handler
+int shiftKey, controlKey; // [HGM] set by mouse handler
int have_sent_ICS_logon = 0;
int movesPerSession;
SendToProgram("force\n", savCps);
DisplayMessage("", "");
if (startedFromSetupPosition) SendBoard(savCps, backwardMostMove);
- for (i = backwardMostMove; i < forwardMostMove; i++) SendMoveToProgram(i, savCps);
+ for (i = backwardMostMove; i < currentMove; i++) SendMoveToProgram(i, savCps);
ThawUI();
SetGNUMode();
}
while(q = strchr(p, SLASH)) p = q+1;
if(*p== NULLCHAR) { DisplayError(_("You did not specify the engine executable"), 0); return; }
if(engineDir[0] != NULLCHAR) {
- ASSIGN(appData.directory[i], engineDir);
+ ASSIGN(appData.directory[i], engineDir); p = engineName;
} else if(p != engineName) { // derive directory from engine path, when not given
p[-1] = 0;
ASSIGN(appData.directory[i], engineName);
if(appData.dualBoard && !twoBoards) { twoBoards = 1; InitDrawingSizes(-2,0); }
if(twoBoards) { partnerUp = 1; flipView = !flipView; } // [HGM] dual
if(partnerUp) DrawPosition(FALSE, partnerBoard);
- if(twoBoards) { partnerUp = 0; flipView = !flipView; } // [HGM] dual
+ if(twoBoards) {
+ DisplayWhiteClock(white_time, to_play == 'W');
+ DisplayBlackClock(black_time, to_play != 'W');
+ partnerUp = 0; flipView = !flipView; } // [HGM] dual
snprintf(partnerStatus, MSG_SIZ,"W: %d:%02d B: %d:%02d (%d-%d) %c", white_time/60000, (white_time%60000)/1000,
(black_time/60000), (black_time%60000)/1000, white_stren, black_stren, to_play);
DisplayMessage(partnerStatus, "");
if(boards[0][fromY][BOARD_WIDTH-2] == 0) boards[0][fromY][BOARD_WIDTH-1] = EmptySquare;
}
} else
- boards[0][fromY][fromX] = EmptySquare;
+ boards[0][fromY][fromX] = gatingPiece;
DrawPosition(FALSE, boards[currentMove]);
return;
}
if (OKToStartUserMove(fromX, fromY)) {
second = 0;
MarkTargetSquares(0);
+ if(gameMode == EditPosition && controlKey) gatingPiece = boards[currentMove][fromY][fromX];
DragPieceBegin(xPix, yPix, FALSE); dragging = 1;
if(appData.sweepSelect && CanPromote(piece = boards[currentMove][fromY][fromX], fromY)) {
promoSweep = defaultPromoChoice;
return bookHit; // notify caller of hit, so it can take action to send move to opponent
}
+int
+LoadError (char *errmess, ChessProgramState *cps)
+{ // unloads engine and switches back to -ncp mode if it was first
+ if(cps->initDone) return FALSE;
+ cps->isr = NULL; // this should suppress further error popups from breaking pipes
+ DestroyChildProcess(cps->pr, 9 ); // just to be sure
+ cps->pr = NoProc;
+ if(cps == &first) {
+ appData.noChessProgram = TRUE;
+ gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu
+ gameMode = BeginningOfGame; ModeHighlight();
+ SetNCPMode();
+ }
+ if(GetDelayedEvent()) CancelDelayedEvent(), ThawUI(); // [HGM] cancel remaining loading effort scheduled after feature timeout
+ DisplayMessage("", ""); // erase waiting message
+ if(errmess) DisplayError(errmess, 0); // announce reason, if given
+ return TRUE;
+}
+
char *savedMessage;
ChessProgramState *savedState;
void
ChessMove moveType;
char promoChar;
char *p, *pv=buf1;
- int machineWhite;
+ int machineWhite, oldError;
char *bookHit;
if(cps == &pairing && sscanf(message, "%d-%d", &savedWhitePlayer, &savedBlackPlayer) == 2) {
return; // Skim the pairing messages here.
}
- cps->userError = 0;
+ oldError = cps->userError; cps->userError = 0;
FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book hit
/*
_(cps->which), cps->program, cps->host, message);
RemoveInputSource(cps->isr);
if(appData.icsActive) DisplayFatalError(buf1, 0, 1); else {
- cps->isr = NULL;
- DestroyChildProcess(cps->pr, 9 ); // just to be sure
- cps->pr = NoProc;
- if(cps == &first) {
- appData.noChessProgram = TRUE;
- gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu
- gameMode = BeginningOfGame; ModeHighlight();
- SetNCPMode();
- }
- if(GetDelayedEvent()) CancelDelayedEvent(), ThawUI(); // [HGM] cancel remaining loading effort scheduled after feature timeout
- DisplayMessage("", ""); // erase waiting message
- DisplayError(buf1, 0);
+ if(LoadError(oldError ? NULL : buf1, cps)) return; // error has then been handled by LoadError
+ if(!oldError) DisplayError(buf1, 0); // if reason neatly announced, suppress general error popup
}
return;
}
int
QuickScan (Board board, Move *move)
{ // reconstruct game,and compare all positions in it
- int cnt=0, stretch=0, total = MakePieceList(board, counts);
+ int cnt=0, stretch=0, total = MakePieceList(board, counts), delayedKing = -1;
do {
int piece = move->piece;
int to = move->to, from = pieceList[piece];
move++;
continue;
} else if(piece <= Q_BCASTL) { // castling, encoded as (Q_XCASTL, king-to) + (rook, rook-to)
+ int rook;
piece = pieceList[piece]; // first two elements of pieceList contain King numbers
from = pieceList[piece]; // so this must be King
quickBoard[from] = 0;
- quickBoard[to] = piece;
pieceList[piece] = to;
- move++;
- continue;
+ from = pieceList[(++move)->piece]; // for FRC this has to be done here
+ quickBoard[from] = 0; // rook
+ quickBoard[to] = piece;
+ to = move->to; piece = move->piece;
+ goto aftercastle;
}
}
if(appData.searchMode > 2) counts[pieceType[quickBoard[to]]]--; // account capture
if((total -= (quickBoard[to] != 0)) < soughtTotal) return -1; // piece count dropped below what we search for
quickBoard[from] = 0;
+ aftercastle:
quickBoard[to] = piece;
pieceList[piece] = to;
cnt++; turn ^= 3;
if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
} else stretch = 0;
if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) return cnt + 1 - stretch;
- move++;
+ move++; delayedKing = -1;
} while(1);
}
AnalyzeFileEvent();
}
- if (!matchMode && pos >= 0) {
+ if (!matchMode && pos > 0) {
ToNrEvent(pos); // [HGM] no autoplay if selected on position
} else
if (matchMode || appData.timeDelay == 0) {
if (appData.noChessProgram) return;
+ if(second.protocolVersion >= 2 && !strstr(second.variants, VariantName(gameInfo.variant))) {
+ DisplayError("second engine does not play this", 0);
+ return;
+ }
+
switch (gameMode) {
case TwoMachinesPlay:
return;
if (count <= 0) {
if (count == 0) {
RemoveInputSource(cps->isr);
- if(!cps->initDone) return; // [HGM] should not generate fatal error during engine load
snprintf(buf, MSG_SIZ, _("Error: %s chess program (%s) exited unexpectedly"),
_(cps->which), cps->program);
- if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
+ if(LoadError(cps->userError ? NULL : buf, cps)) return; // [HGM] should not generate fatal error during engine load
+ if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
if((signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {
snprintf(buf, MSG_SIZ, _("%s program exits in draw position (%s)"), _(cps->which), cps->program);
if(matchMode && appData.tourneyFile[0]) { cps->pr = NoProc; GameEnds(GameIsDrawn, buf, GE_XBOARD); return; }
if(sscanf(p, " -check %d", &def) < 1) return FALSE;
opt->value = (def != 0);
opt->type = CheckBox;
- } else if(p = strstr(opt->name, " -combo ")) {
- opt->textValue = (char*) (&cps->comboList[cps->comboCnt]); // cheat with pointer type
+ } else if(p = strstr(opt->name, " -combo ")) {
+ opt->textValue = (char*) (opt->choice = &cps->comboList[cps->comboCnt]); // cheat with pointer type
cps->comboList[cps->comboCnt++] = q = p+8; // holds possible choices
if(*q == '*') cps->comboList[cps->comboCnt-1]++;
opt->value = n = 0;
if (BoolFeature(&p, "memory", &cps->memSize, cps)) continue;
if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;
if (StringFeature(&p, "egt", cps->egtFormats, cps)) continue;
- if (StringFeature(&p, "option", cps->option[cps->nrOptions].name, cps)) {
+ if (StringFeature(&p, "option", buf, cps)) {
+ FREE(cps->option[cps->nrOptions].name);
+ cps->option[cps->nrOptions].name = malloc(MSG_SIZ);
+ safeStrCpy(cps->option[cps->nrOptions].name, buf, MSG_SIZ);
if(!ParseOption(&(cps->option[cps->nrOptions++]), cps)) { // [HGM] options: add option feature
snprintf(buf, MSG_SIZ, "rejected option %s\n", cps->option[--cps->nrOptions].name);
SendToProgram(buf, cps);