InitEngineUCI( installDir, cps ); // [HGM] moved here from winboard.c, to make available in xboard
}
+ChessProgramState *savCps;
+
+void
+LoadEngine()
+{
+ int i;
+ if(WaitForEngine(savCps, LoadEngine)) return;
+ CommonEngineInit(); // recalculate time odds
+ if(gameInfo.variant != StringToVariant(appData.variant)) {
+ // we changed variant when loading the engine; this forces us to reset
+ Reset(TRUE, savCps != &first);
+ EditGameEvent(); // for consistency with other path, as Reset changes mode
+ }
+ InitChessProgram(savCps, FALSE);
+ SendToProgram("force\n", savCps);
+ DisplayMessage("", "");
+ if (startedFromSetupPosition) SendBoard(savCps, backwardMostMove);
+ for (i = backwardMostMove; i < forwardMostMove; i++) SendMoveToProgram(i, savCps);
+ ThawUI();
+ SetGNUMode();
+}
+
+void
+ReplaceEngine(ChessProgramState *cps, int n)
+{
+ EditGameEvent();
+ UnloadEngine(cps);
+ appData.noChessProgram = False;
+ appData.clockMode = True;
+ InitEngine(cps, n);
+ savCps = cps; // parameter to LoadEngine passed as globals, to allow scheduled calling :-(
+ LoadEngine();
+}
+
void
InitBackEnd1()
{
DelayedEventCallback cb = GetDelayedEvent();
if ((cb == InitBackEnd3 && cps == &first) ||
(cb == SettingsMenuIfReady && cps == &second) ||
+ (cb == LoadEngine) ||
(cb == TwoMachinesEventIfReady && cps == &second)) {
CancelDelayedEvent();
ScheduleDelayedEvent(cb, val ? 1 : 3600000);
void OptionsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
void IcsTextProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void LoadEngineProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
};
MenuItem engineMenu[] = {
+ {N_("Load New Engine ..."), "Load Engine", LoadEngineProc},
+ {"----", NULL, NothingProc},
{N_("Engine #1 Settings ..."), "Engine #1 Settings", FirstSettingsProc},
{N_("Engine #2 Settings ..."), "Engine #2 Settings", SecondSettingsProc},
{"----", NULL, NothingProc},
#endif
{ "menuEngine.Engine #1 Settings", False },
{ "menuEngine.Engine #2 Settings", False },
+ { "menuEngine.Load Engine", False },
{ "menuEdit.Annotate", False },
{ NULL, False }
};
{ "menuFile.Mail Move", False },
{ "menuFile.Reload CMail Message", False },
+ // [HGM] The following have been added to make a switch from ncp to GNU mode possible
+ { "menuMode.Machine White", True },
+ { "menuMode.Machine Black", True },
+ { "menuMode.Analysis Mode", True },
+ { "menuMode.Analyze File", True },
+ { "menuMode.Two Machines", True },
+ { "menuMode.Machine Match", True },
+ { "menuEngine.Engine #1 Settings", True },
+ { "menuEngine.Engine #2 Settings", True },
+ { "menuEngine.Hint", True },
+ { "menuEngine.Book", True },
+ { "menuEngine.Move Now", True },
+ { "menuEngine.Retract Move", True },
+ { "Action", True },
{ NULL, False }
};
SettingsPopUp(&second);
}
+char *engineName, *engineDir, *engineChoice, *engineLine;
+Boolean isUCI, hasBook, storeVariant, v1, addToList;
+extern Option installOptions[];
+extern char *firstChessProgramNames;
+char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL };
+char *engineList[100] = {" "}, *engineMnemonic[100] = {""};
+
+void NamesToList(char *names)
+{
+ char buf[MSG_SIZ], *p, *q;
+ int i=1;
+ while(*names) {
+ p = names; q = buf;
+ while(*p && *p != '\n') *q++ = *p++;
+ *q = 0;
+ if(engineList[i]) free(engineList[i]);
+ engineList[i] = strdup(buf);
+ if(*p == '\n') p++;
+ TidyProgramName(engineList[i], "localhost", buf);
+ if(engineMnemonic[i]) free(engineMnemonic[i]);
+ if(q = strstr(engineList[i], " -variant ")) {
+ strcat(buf, "(");
+ sscanf(q + 10, "%s", buf + strlen(buf));
+ strcat(buf, ")");
+ }
+ engineMnemonic[i] = strdup(buf);
+ names = p; i++;
+ }
+ engineList[i] = NULL;
+}
+
+// following implemented as macro to avoid type limitations
+#define SWAP(item, temp) temp = appData.item[0]; appData.item[0] = appData.item[n]; appData.item[n] = temp;
+
+void SwapEngines(int n)
+{ // swap settings for first engine and other engine (so far only some selected options)
+ int h;
+ char *p;
+ if(n == 0) return;
+ SWAP(directory, p)
+ SWAP(chessProgram, p)
+ SWAP(isUCI, h)
+ SWAP(hasOwnBookUCI, h)
+ SWAP(protocolVersion, h)
+ SWAP(reuse, h)
+ SWAP(scoreIsAbsolute, h)
+ SWAP(timeOdds, h)
+}
+
+void Load(ChessProgramState *cps, int i)
+{
+ char *p, *q, buf[MSG_SIZ];
+ if(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*
+ ParseArgsFromString(buf);
+ SwapEngines(i);
+ ReplaceEngine(cps, i);
+ return;
+ }
+ p = engineName;
+ while(q = strchr(p, '/')) p = q+1;
+ if(*p== NULLCHAR) return;
+ appData.chessProgram[i] = strdup(p);
+ if(engineDir[0] != NULLCHAR)
+ appData.directory[i] = engineDir;
+ else if(p != engineName) { // derive directory from engine path, when not given
+ p[-1] = 0;
+ appData.directory[i] = strdup(engineName);
+ p[-1] = '/';
+ } else appData.directory[i] = ".";
+ appData.isUCI[i] = isUCI;
+ appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
+ appData.hasOwnBookUCI[i] = hasBook;
+ if(addToList) {
+ int len;
+ q = firstChessProgramNames;
+ snprintf(buf, MSG_SIZ, "\"%s\" -fd \"%s\"%s%s%s%s%s\n", p, appData.directory[i],
+ v1 ? " -firstProtocolVersion 1" : "",
+ hasBook ? "" : " -fNoOwnBookUCI",
+ isUCI ? " -fUCI" : "",
+ storeVariant ? " -variant " : "",
+ storeVariant ? VariantName(gameInfo.variant) : "");
+printf("new line: %s", buf);
+ firstChessProgramNames = malloc(len = strlen(q) + strlen(buf) + 1);
+ snprintf(firstChessProgramNames, len, "%s%s", q, buf);
+ if(q) free(q);
+ }
+ ReplaceEngine(cps, i);
+}
+
+void InstallOK(int n)
+{
+ PopDown(0); // early popdown, to allow FreezeUI to instate grab
+ if(engineChoice[0] == engineNr[0][0]) Load(&first, 0); else Load(&second, 1);
+}
+
+Option installOptions[] = {
+{ 0, 0, 0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") },
+{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },
+{ 0, 0, 0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("Engine Directory:") },
+{ 0, 0, 0, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine Command:") },
+{ 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when empty)") },
+{ 0, 0, 0, NULL, (void*) &isUCI, NULL, NULL, CheckBox, N_("UCI") },
+{ 0, 0, 0, NULL, (void*) &v1, NULL, NULL, CheckBox, N_("WB protocol v1 (do not wait for engine features)") },
+{ 0, 0, 0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") },
+{ 0, 0, 0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") },
+{ 0, 0, 0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") },
+{ 0, 0, 0, NULL, (void*) &engineChoice, (char*) engineNr, engineNr, ComboBox, N_("Load mentioned engine as") },
+{ 0, 1, 0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" }
+};
+
+void LoadEngineProc(w, event, prms, nprms)
+ Widget w;
+ XEvent *event;
+ String *prms;
+ Cardinal *nprms;
+{
+ isUCI = addToList = storeVariant = v1 = False; hasBook = True; // defaults
+ engineDir = "";
+ if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);
+ if(engineLine) free(engineLine); engineLine = strdup("");
+ NamesToList(firstChessProgramNames);
+ GenericPopUp(installOptions, _("Load engine"), 0);
+}
+
//---------------------------- Chat Windows ----------------------------------------------
void OutputChatMessage(int partner, char *mess)