Board boards[MAX_MOVES];
/* [HGM] Following 7 needed for accurate legality tests: */
signed char castlingRank[BOARD_FILES]; // and corresponding ranks
-signed char initialRights[BOARD_FILES];
+unsigned char initialRights[BOARD_FILES];
int nrCastlingRights; // For TwoKings, or to implement castling-unknown status
int initialRulePlies, FENrulePlies;
FILE *serverMoves = NULL; // next two for broadcasting (/serverMoves option)
static ClickType lastClickType;
int
+PieceInString (char *s, ChessSquare piece)
+{
+ char *p, ID = ToUpper(PieceToChar(piece)), suffix = PieceSuffix(piece);
+ while((p = strchr(s, ID))) {
+ if(!suffix || p[1] == suffix) return TRUE;
+ s = p;
+ }
+ return FALSE;
+}
+
+int
Partner (ChessSquare *p)
{ // change piece into promotion partner if one shogi-promotes to the other
- int stride = gameInfo.variant == VariantChu ? WhiteTokin : 11;
- ChessSquare partner;
- partner = (*p/stride & 1 ? *p - stride : *p + stride);
+ ChessSquare partner = promoPartner[*p];
if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0;
*p = partner;
return 1;
if(!step) step = -1;
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' ||
!toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other
- promoRestrict[0] ? !strchr(promoRestrict, ToUpper(PieceToChar(promoSweep))) : // if choice set available, use it
+ promoRestrict[0] ? !PieceInString(promoRestrict, promoSweep) : // if choice set available, use it
promoSweep == pawn ||
appData.testLegality && (promoSweep == king || gameInfo.variant != VariantChuChess &&
(promoSweep == WhiteLion || promoSweep == BlackLion)));
{
int n = 0;
if(!*escapes) return strlen(s);
- while(*s) n += (*s != '/' && !strchr(escapes, *s)), s++;
+ while(*s) n += (*s != '-' && *s != '^' && *s != '*' && !strchr(escapes, *s)), s++;
return n;
}
+static int pieceOrder[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // P N B R Q F E A C W M
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, // O H I J G D V L S U Lion
+ 45, 23, 24, 25, 26, 27, 28, 29, 46, 31, 32, // Sword Zebra Camel Tower Wolf Dragon Duck Axe Leopard Gnu Cub
+ 44, 51, 56, 57, 58, 59, 60, 61, 62, 63, 34, // Whale Pegasus Wizard Copper Iron Viking Flag Amazon Wheel Shield Claw
+ 33, 55, 53, 42, 37, 48, 39, 40, 41, 22, 30, // +P +N =B =R +L +S +E +Ph +Kn Butterfly Hat
+ 38, 43, 35, 36, 49, 47, 52, 50, 54, 64, 65 // +V +M =H =D Princess HSword +GB HCrown Wheer Shierd King
+};
+
int
SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
/* [HGM] moved here from winboard.c because of its general usefulness */
/* Basically a safe strcpy that uses the last character as King */
{
- int result = FALSE; int NrPieces, offs;
+ int result = FALSE; int NrPieces;
+ unsigned char partner[EmptySquare];
if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare
&& NrPieces >= 12 && !(NrPieces&1)) {
- int i, j = 0; /* [HGM] Accept even length from 12 to 88 */
+ int i, ii, j = 0; /* [HGM] Accept even length from 12 to 88 */
for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
- for( i=offs=0; i<NrPieces/2-1; i++ ) {
- char *p;
- if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
- table[i + offs] = map[j++];
- if(p = strchr(escapes, map[j])) j++, table[i + offs] += 64*(p - escapes + 1);
+ for( ii=0; ii<NrPieces/2-1; ii++ ) {
+ char *p, c=0;
+ i = pieceOrder[ii];
+ if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
+ table[i] = map[j++];
+ if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
+ if(c) partner[i] = table[i], table[i] = c;
}
table[(int) WhiteKing] = map[j++];
- for( i=offs=0; i<NrPieces/2-1; i++ ) {
- char *p;
- if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
- table[WHITE_TO_BLACK i + offs] = map[j++];
- if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i + offs] += 64*(p - escapes + 1);
+ for( ii=0; ii<NrPieces/2-1; ii++ ) {
+ char *p, c=0;
+ i = WHITE_TO_BLACK pieceOrder[ii];
+ if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
+ table[i] = map[j++];
+ if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
+ if(c) partner[i] = table[i], table[i] = c;
}
table[(int) BlackKing] = map[j++];
+
+ if(*escapes) { // set up promotion pairing
+ for( i=0; i<(int) EmptySquare; i++ ) promoPartner[i] = (i%BlackPawn < 11 ? i + 11 : i%BlackPawn < 22 ? i - 11 : i); // default
+ // pieceToChar entirely filled, so we can look up specified partners
+ for(i=0; i<EmptySquare; i++) { // adjust promotion pairing
+ int c = table[i];
+ if(c == '^' || c == '-') { // has specified partner
+ int p;
+ for(p=0; p<EmptySquare; p++) if(table[p] == partner[i]) break;
+ if(c == '^') table[i] = '+';
+ if(p < EmptySquare) promoPartner[p] = i, promoPartner[i] = p; // marry them
+ } else if(c == '*') promoPartner[i] = (i < BlackPawn ? WhiteTokin : BlackTokin); // promotes to Tokin
+ }
+ }
+
result = TRUE;
}
initialPosition[CASTLING][i] = initialRights[i] = NoRights; /* but no rights yet */
initialPosition[EP_STATUS] = EP_NONE;
initialPosition[TOUCHED_W] = initialPosition[TOUCHED_B] = 0;
- SetCharTable(pieceToChar, "PNBRQ...........Kpnbrq...........k");
+ SetCharTableEsc(pieceToChar, "PNBRQ...........Kpnbrq...........k", SUFFIXES);
if(startVariant == gameInfo.variant) // [HGM] nicks: enable nicknames in original variant
SetCharTable(pieceNickName, appData.pieceNickNames);
else SetCharTable(pieceNickName, "............");
gameInfo.boardWidth = 12;
gameInfo.boardHeight = 12;
nrCastlingRights = 0;
- SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/+.++.++++++++++.+++++K"
- "p.brqsexogcathd.vmlifn/+.++.++++++++++.+++++k", SUFFIXES);
+ SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/^P.^B^R.^S^E^X^O^G^C^A^T^H^D.^V^M^L^I^FK"
+ "p.brqsexogcathd.vmlifn/^p.^b^r.^s^e^x^o^g^c^a^t^h^d.^v^m^l^i^fk", SUFFIXES);
break;
case VariantCourier:
pieces = CourierArray;
piece = boards[currentMove][fromY][fromX];
if(gameInfo.variant == VariantChu) {
- int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece;
promotionZoneSize = BOARD_HEIGHT/3;
- highestPromotingPiece = (p >= WhiteTokin || PieceToChar(piece + WhiteTokin) != '+') ? WhitePawn : WhiteTokin-1;
+ highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing;
} else if(gameInfo.variant == VariantShogi) {
promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8);
highestPromotingPiece = (int)WhiteAlfil;
char *p, *q, buf[MSG_SIZ];
int n, min = (-1)<<31, max = 1<<31, def;
+ opt->target = &opt->value; // OK for spin/slider and checkbox
if(p = strstr(opt->name, " -spin ")) {
if((n = sscanf(p, " -spin %d %d %d", &def, &min, &max)) < 3 ) return FALSE;
if(max < min) max = min; // enforce consistency
} else if((p = strstr(opt->name, " -string "))) {
opt->textValue = p+9;
opt->type = TextBox;
+ opt->target = &opt->textValue;
} else if((p = strstr(opt->name, " -file "))) {
// for now -file is a synonym for -string, to already provide compatibility with future polyglots
- opt->textValue = p+7;
+ opt->target = opt->textValue = p+7;
opt->type = FileName; // FileName;
+ opt->target = &opt->textValue;
} else if((p = strstr(opt->name, " -path "))) {
// for now -file is a synonym for -string, to already provide compatibility with future polyglots
- opt->textValue = p+7;
+ opt->target = opt->textValue = p+7;
opt->type = PathName; // PathName;
+ opt->target = &opt->textValue;
} else if(p = strstr(opt->name, " -check ")) {
if(sscanf(p, " -check %d", &def) < 1) return FALSE;
opt->value = (def != 0);
(cb == TwoMachinesEventIfReady)) {
CancelDelayedEvent();
ScheduleDelayedEvent(cb, val ? 1 : 3600000);
- }
+ } else if(!val && !cps->reload) ClearOptions(cps); // let 'spurious' done=0 clear engine's option list
cps->initDone = val;
- if(val) cps->reload = FALSE;
+ if(val) cps->reload = FALSE, RefreshSettingsDialog(cps, val);
}
/* Parse feature command from engine */