return retbuf;
}
+char engineVariant[MSG_SIZ];
char *variantNames[] = VARIANT_NAMES;
char *
VariantName (VariantClass v)
{
+ if(v == VariantUnknown) return engineVariant;
return variantNames[v];
}
}
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;
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;
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)
{
extern char *recentEngines;
extern char *comboLine;
extern Boolean partnerUp, twoBoards;
+extern char engineVariant[];
+char *EngineDefinedVariant P((ChessProgramState *cps, int n));
void SettingsPopUp P((ChessProgramState *cps)); // [HGM] really in front-end, but CPS not known in frontend.h
int WaitForEngine P((ChessProgramState *cps, DelayedEventCallback x));
void Load P((ChessProgramState *cps, int n));
case SaveButton:
case Label:
case Break:
+ case -1:
break;
}
if(opts[i].type == EndMark) break;
{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
//{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
{ VariantCourier, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")},
+// optional buttons for engine-defined variants
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
+{ VariantUnknown, SAME_ROW,135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
{ 0, NO_OK, 0, NULL, NULL, "", NULL, EndMark , "" }
};
Pick (int n)
{
VariantClass v = variantDescriptors[n].value;
+ if(v == VariantUnknown) safeStrCpy(engineVariant, variantDescriptors[n].name, MSG_SIZ);
if(!appData.noChessProgram) {
char *name = VariantName(v), buf[MSG_SIZ];
if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
void
NewVariantProc ()
{
+ static int start;
+ int i, last;
if(appData.noChessProgram) sprintf(warning, _("Only bughouse is not available in viewer mode")); else
sprintf(warning, _("All variants not supported by first engine\n(currently %s) are disabled"), first.tidy);
+ if(!start) while(variantDescriptors[start].type != -1) start++; // locate first spare
+ last = -1;
+ for(i=0; i<6; i++) { // create buttons for engine-defined variants
+ char *v = EngineDefinedVariant(&first, i);
+ if(v) {
+ last = i;
+ ASSIGN(variantDescriptors[start+i].name, v);
+ variantDescriptors[start+i].type = Button;
+ } else variantDescriptors[start+i].type = -1;
+ if(!(last&1)) { // odd number, add filler
+ ASSIGN(variantDescriptors[start+last+1].name, " ");
+ variantDescriptors[start+last+1].type = Button;
+ }
+ }
GenericPopUp(variantDescriptors, _("New Variant"), TransientDlg, BoardWindow, MODAL, 0);
}
#define OPT_VariantSpartan 1531\r
#define OPT_VariantASEAN 1532\r
#define OPT_VariantGrand 1534\r
+#define OPT_EngineVariant 1560\r
#define IDC_Files 1550\r
#define IDC_Ranks 1551\r
#define IDC_Holdings 1552\r
10\r
CONTROL "&xiangqi",OPT_VariantXiangqi,"Button",BS_AUTORADIOBUTTON,154,114,70,\r
10\r
- GROUPBOX "Variant",GPB_Variant,4,4,215,125\r
- LTEXT "Board size:",GPB_Board,10,165,40,8,WS_TABSTOP\r
- LTEXT "ranks",IDC_Height,77,165,38,8\r
- EDITTEXT IDC_Ranks,60,161,14,14,ES_AUTOHSCROLL\r
- LTEXT "files",IDC_Width,133,165,80,8\r
- EDITTEXT IDC_Files,116,161,14,14,ES_AUTOHSCROLL\r
- LTEXT "Holdings with room for:",IDC_Hand,10,183,90,8\r
- EDITTEXT IDC_Holdings,93,179,14,14,ES_AUTOHSCROLL\r
- LTEXT "pieces",IDC_Pieces,110,183,100,8\r
- LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,201,210,8\r
+ CONTROL "",OPT_EngineVariant+0,"Button",BS_AUTORADIOBUTTON,9,134,70,10\r
+ CONTROL "",OPT_EngineVariant+1,"Button",BS_AUTORADIOBUTTON,80,134,70,10\r
+ CONTROL "",OPT_EngineVariant+2,"Button",BS_AUTORADIOBUTTON,154,134,70,10\r
+ CONTROL "",OPT_EngineVariant+3,"Button",BS_AUTORADIOBUTTON,9,144,70,10\r
+ CONTROL "",OPT_EngineVariant+4,"Button",BS_AUTORADIOBUTTON,80,144,70,10\r
+ CONTROL "",OPT_EngineVariant+5,"Button",BS_AUTORADIOBUTTON,154,144,70,10\r
+ CONTROL "",OPT_EngineVariant+6,"Button",BS_AUTORADIOBUTTON,9,154,70,10\r
+ CONTROL "",OPT_EngineVariant+7,"Button",BS_AUTORADIOBUTTON,80,154,70,10\r
+ CONTROL "",OPT_EngineVariant+8,"Button",BS_AUTORADIOBUTTON,154,154,70,10\r
+ GROUPBOX "Variant",GPB_Variant,4,4,215,165\r
+ LTEXT "Board size:",GPB_Board,10,183,40,8,WS_TABSTOP\r
+ LTEXT "ranks",IDC_Height,77,183,38,8\r
+ EDITTEXT IDC_Ranks,60,179,14,14,ES_AUTOHSCROLL\r
+ LTEXT "files",IDC_Width,133,183,80,8\r
+ EDITTEXT IDC_Files,116,179,14,14,ES_AUTOHSCROLL\r
+ LTEXT "Holdings with room for:",IDC_Hand,10,201,90,8\r
+ EDITTEXT IDC_Holdings,93,197,14,14,ES_AUTOHSCROLL\r
+ LTEXT "pieces",IDC_Pieces,110,201,100,8\r
+ LTEXT "('-1' means defaults for selected variant)",IDC_Def,10,217,210,8\r
DEFPUSHBUTTON "OK",IDOK,114,232,50,14\r
PUSHBUTTON "Cancel",IDCANCEL,170,232,50,14\r
END\r
if(IsDlgButtonChecked(hDlg, j) &&\r
(appData.noChessProgram || strstr(first.variants, VariantName(i-1)))) return (VariantClass) i-1;\r
}\r
+ for(i=0; i<9; i++) { // check for engine-defined variants\r
+ if(IsDlgButtonChecked(hDlg, OPT_EngineVariant+i) ) {\r
+ GetDlgItemText(hDlg, OPT_EngineVariant+i, engineVariant, MSG_SIZ); // remember name, so we can resolve it later\r
+ return VariantUnknown;\r
+ }\r
+ }\r
return gameInfo.variant; // If no button checked, keep old\r
}\r
\r
if(j == -1) continue; // no menu button\r
EnableWindow(GetDlgItem(hDlg, j), appData.noChessProgram || strstr(first.variants, VariantName(i-1)));\r
}\r
+ for(i=0; i<9; i++) { // initialize engine-defined variants\r
+ char *v = EngineDefinedVariant(&first, i); // get name of #i\r
+ if(v) { // there is such a variant\r
+ EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), TRUE); // and enable the button\r
+ SetDlgItemText(hDlg, OPT_EngineVariant+i, v); // put its name on button\r
+ } else EnableWindow(GetDlgItem(hDlg, OPT_EngineVariant+i), FALSE); // no such variant; disable button\r
+ }\r
}\r
\r
LRESULT CALLBACK\r
UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);\r
break;\r
\r
+\r
case OPT_ChooseNormalColor:\r
ColorizeTextPopup(hDlg, ColorNormal);\r
UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);\r