FILE *WriteTourneyFile P((char *results, FILE *f));
void DisplayTwoMachinesTitle P(());
static void ExcludeClick P((int index));
+void ToggleSecond P((void));
#ifdef WIN32
extern void ConsoleCreate();
/* Send . command to Crafty to collect stats */
SendToProgram(".\n", &first);
+ if(second.analyzing) SendToProgram(".\n", &second);
/* Don't send another until we get a response (this makes
us stop sending to old Crafty's which don't understand
for(i = backwardMostMove; i<last; i++) {
char buf[20];
snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%s\n", parseList[i]);
+ if((*buf == 'b' || *buf == 'B') && buf[1] == 'x') { // work-around for stupid FICS bug, which thinks bxc3 can be a Bishop move
+ int len = strlen(moveList[i]);
+ snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%s", moveList[i]); // use long algebraic
+ if(!isdigit(buf[len-2])) snprintf(buf+len-2, 20-len, "=%c\n", ToUpper(buf[len-2])); // promotion must have '=' in ICS format
+ }
SendToICS(buf);
}
SendToICS(ics_prefix);
}
Boolean
-LoadMultiPV (int x, int y, char *buf, int index, int *start, int *end)
+LoadMultiPV (int x, int y, char *buf, int index, int *start, int *end, int pane)
{
int startPV, multi, lineStart, origIndex = index;
char *p, buf2[MSG_SIZ];
+ ChessProgramState *cps = (pane ? &second : &first);
if(index < 0 || index >= strlen(buf)) return FALSE; // sanity
lastX = x; lastY = y;
do{ while(buf[index] && buf[index] != '\n') index++;
} while(buf[index] == '\n' && buf[index+1] == '\\' && buf[index+2] == ' ' && index++); // join kibitzed PV continuation line
buf[index] = 0;
- if(lineStart == 0 && gameMode == AnalyzeMode && (multi = MultiPV(&first)) >= 0) {
- int n = first.option[multi].value;
+ if(lineStart == 0 && gameMode == AnalyzeMode && (multi = MultiPV(cps)) >= 0) {
+ int n = cps->option[multi].value;
if(origIndex > 17 && origIndex < 24) { if(n>1) n--; } else if(origIndex > index - 6) n++;
snprintf(buf2, MSG_SIZ, "option MultiPV=%d\n", n);
- if(first.option[multi].value != n) SendToProgram(buf2, &first);
- first.option[multi].value = n;
+ if(cps->option[multi].value != n) SendToProgram(buf2, cps);
+ cps->option[multi].value = n;
*start = *end = 0;
return FALSE;
} else if(strstr(buf+lineStart, "exclude:") == buf+lineStart) { // exclude moves clicked
}
/* Relay move to ICS or chess engine */
+ if(second.analyzing) ToggleSecond(); // for now, we just stop second analyzing engine
if (appData.icsActive) {
if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
gameMode == IcsExamining) {
&& fromX != toX && fromY != toY)
fprintf(serverMoves, ":%c%c:%c%c", AAA+fromX, ONE+fromY, AAA+toX, ONE+fromY);
// promotion suffix
- if(promoChar != NULLCHAR)
- fprintf(serverMoves, ":%c:%c%c", ToLower(promoChar), AAA+toX, ONE+toY);
+ if(promoChar != NULLCHAR) {
+ if(fromY == 0 || fromY == BOARD_HEIGHT-1)
+ fprintf(serverMoves, ":%c%c:%c%c", WhiteOnMove(forwardMostMove) ? 'w' : 'b',
+ ToLower(promoChar), AAA+fromX, ONE+fromY); // Seirawan gating
+ else fprintf(serverMoves, ":%c:%c%c", ToLower(promoChar), AAA+toX, ONE+toY);
+ }
if(!loadFlag) {
char buf[MOVE_LEN*2], *p; int len;
fprintf(serverMoves, "/%d/%d",
else timeLeft = blackTimeRemaining/1000;
fprintf(serverMoves, "/%d", timeLeft);
strncpy(buf, parseList[forwardMostMove], MOVE_LEN*2);
+ if(p = strchr(buf, '/')) *p = NULLCHAR; else
if(p = strchr(buf, '=')) *p = NULLCHAR;
len = strlen(buf); if(len > 1 && buf[len-2] != '-') buf[len-2] = NULLCHAR; // strip to-square
fprintf(serverMoves, "/%s", buf);
}
int
+CheckPlayers (char *participants)
+{
+ int i;
+ char buf[MSG_SIZ], *p;
+ NamesToList(firstChessProgramNames, command, mnemonic, "all");
+ while(p = strchr(participants, '\n')) {
+ *p = NULLCHAR;
+ for(i=1; mnemonic[i]; i++) if(!strcmp(participants, mnemonic[i])) break;
+ if(!mnemonic[i]) {
+ snprintf(buf, MSG_SIZ, _("No engine %s is installed"), participants);
+ *p = '\n';
+ DisplayError(buf, 0);
+ return 1;
+ }
+ *p = '\n';
+ participants = p + 1;
+ }
+ return 0;
+}
+
+int
CreateTourney (char *name)
{
FILE *f;
DisplayError(_("Not enough participants"), 0);
return 0;
}
+ if(CheckPlayers(appData.participants)) return 0;
ASSIGN(appData.tourneyFile, name);
if(appData.tourneyType < 0) appData.defaultMatchGames = 1; // Swiss forces games/pairing = 1
if((f = WriteTourneyFile("", NULL)) == NULL) return 0;
}
int
+GetEngineLine (char *s, int n)
+{
+ int i;
+ char buf[MSG_SIZ];
+ extern char *icsNames;
+ if(!s || !*s) return 0;
+ NamesToList(n == 10 ? icsNames : firstChessProgramNames, command, mnemonic, "all");
+ for(i=1; mnemonic[i]; i++) if(!strcmp(s, mnemonic[i])) break;
+ if(!mnemonic[i]) return 0;
+ snprintf(buf, MSG_SIZ, "-%s %s", n == 10 ? "icshost" : "fcp", command[i]);
+ if(n == 1) SwapEngines(n);
+ ParseArgsFromString(buf);
+ if(n == 1) SwapEngines(n);
+ if(n == 0 && *appData.secondChessProgram == NULLCHAR) {
+ SwapEngines(1); // set second same as first if not yet set (to suppress WB startup dialog)
+ ParseArgsFromString(buf);
+ }
+ return 1;
+}
+
+int
SetPlayer (int player, char *p)
{ // [HGM] find the engine line of the partcipant given by number, and parse its options.
int i;
}
void
+ToggleSecond ()
+{
+ if(second.analyzing) {
+ SendToProgram("exit\n", &second);
+ second.analyzing = FALSE;
+ } else {
+ if (second.pr == NoProc) StartChessProgram(&second);
+ InitChessProgram(&second, FALSE);
+ FeedMovesToProgram(&second, currentMove);
+
+ SendToProgram("analyze\n", &second);
+ second.analyzing = TRUE;
+ }
+}
+
+void
AnalyzeModeEvent ()
{
+ if (gameMode == AnalyzeMode) { ToggleSecond(); return; }
if (appData.noChessProgram || gameMode == AnalyzeMode)
return;
SendToProgram("exit\n", &first);
first.analyzing = FALSE;
}
+ if (second.analyzing) {
+ SendToProgram("exit\n", &second);
+ second.analyzing = FALSE;
+ }
thinkOutput[0] = NULLCHAR;
}
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) {
+ 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 (gameMode == EditGame || gameMode == AnalyzeMode ||
gameMode == Training || gameMode == PlayFromGameFile ||
gameMode == AnalyzeFile) {
+ if(target != currentMove && second.analyzing) ToggleSecond(); // for now, we just stop second analyzing engine
while (currentMove < target) {
SendMoveToProgram(currentMove++, &first);
}
}
if (gameMode == EditGame || gameMode==AnalyzeMode ||
gameMode == PlayFromGameFile || gameMode == AnalyzeFile) {
+ if(target != currentMove && second.analyzing) ToggleSecond(); // for now, we just stop second analyzing engine
while (currentMove > target) {
if(moveList[currentMove-1][1] == '@' && moveList[currentMove-1][0] == '@') {
// null move cannot be undone. Reload program with move history before it.
boards[move][CASTLING][2] != NoRights ) k = 1, *p++ = 'K';
q = (boards[move][CASTLING][1] == BOARD_LEFT &&
boards[move][CASTLING][2] != NoRights );
- if(gameInfo.variant = VariantSChess) { // for S-Chess, indicate all vrgin backrank pieces
+ if(gameInfo.variant == VariantSChess) { // for S-Chess, indicate all vrgin backrank pieces
for(i=j=0; i<BOARD_HEIGHT; i++) j += boards[move][i][BOARD_RGHT]; // count white held pieces
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q && j; i--)
if((boards[move][0][i] != WhiteKing || k+q == 0) &&
boards[move][CASTLING][5] != NoRights ) k = 1, *p++ = 'k';
q = (boards[move][CASTLING][4] == BOARD_LEFT &&
boards[move][CASTLING][5] != NoRights );
- if(gameInfo.variant = VariantSChess) {
+ if(gameInfo.variant == VariantSChess) {
for(i=j=0; i<BOARD_HEIGHT; i++) j += boards[move][i][BOARD_LEFT-1]; // count black held pieces
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q && j; i--)
if((boards[move][BOARD_HEIGHT-1][i] != BlackKing || k+q == 0) &&