X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=fd730e947baa873b374d67c835b3b3ecee985d55;hb=ec51c847ed215b286d5ca730a4984819403d5194;hp=3254ff7709c4fdb2f1ec7cadd987564c1a760ad7;hpb=4a93b2d0743219a65784b043395cda77fa80662c;p=xboard.git diff --git a/backend.c b/backend.c index 3254ff7..fd730e9 100644 --- a/backend.c +++ b/backend.c @@ -192,7 +192,6 @@ void GameEnds P((ChessMove result, char *resultDetails, int whosays)); void EditPositionDone P((Boolean fakeRights)); void PrintOpponents P((FILE *fp)); void PrintPosition P((FILE *fp, int move)); -void StartChessProgram P((ChessProgramState *cps)); void SendToProgram P((char *message, ChessProgramState *cps)); void SendMoveToProgram P((int moveNum, ChessProgramState *cps)); void ReceiveFromProgram P((InputSourceRef isr, VOIDSTAR closure, @@ -516,7 +515,7 @@ AppData appData; 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) @@ -4890,13 +4889,13 @@ ParseBoard12 (char *string) if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves old = (k==toY && j==toX) ? boards[moveNum-1][fromY][fromX] : boards[moveNum-1][k][j]; // trace back mover if(old == new) continue; - if(old == PROMOTED new) boards[moveNum][k][j] = old; // prevent promoted pieces to revert to primordial ones + if(old == PROMOTED(new)) boards[moveNum][k][j] = old;// prevent promoted pieces to revert to primordial ones else if(new == WhiteWazir || new == BlackWazir) { if(old < WhiteCannon || old >= BlackPawn && old < BlackCannon) - boards[moveNum][k][j] = PROMOTED old; // choose correct type of Gold in promotion + boards[moveNum][k][j] = PROMOTED(old); // choose correct type of Gold in promotion else boards[moveNum][k][j] = old; // preserve type of Gold } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!) - boards[moveNum][k][j] = PROMOTED new; // use non-primordial representation of chosen piece + boards[moveNum][k][j] = PROMOTED(new); // use non-primordial representation of chosen piece } } else { /* Move from ICS was illegal!? Punt. */ @@ -5381,12 +5380,22 @@ int dragging; 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; + if(PieceToChar(*p) == '+') partner = boards[currentMove][fromY][fromX]; *p = partner; return 1; } @@ -5411,7 +5420,7 @@ Sweep (int step) 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))); @@ -5994,37 +6003,69 @@ ptclen (const char *s, char *escapes) { 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; ialphaRank) { /* [HGM] shogi: translate coords */ @@ -6465,7 +6506,7 @@ SendBoard (ChessProgramState *cps, int moveNum) AAA + j, ONE + i - '0'); if(message[0] == '+' || message[0] == '~') { snprintf(message, MSG_SIZ,"%c%c%d+\n", - PieceToChar((ChessSquare)(DEMOTED *bp)), + PieceToChar((ChessSquare)(DEMOTED(*bp))), AAA + j, ONE + i - '0'); } if(cps->alphaRank) { /* [HGM] shogi: translate coords */ @@ -6630,9 +6671,8 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i 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; @@ -7037,7 +7077,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) if(!appData.pieceMenu && toX == fromX && toY == fromY && boards[0][rf][ff] != EmptySquare) { ChessSquare q, p = boards[0][rf][ff]; if(p >= BlackPawn) p = BLACK_TO_WHITE p; - if(CHUPROMOTED p < BlackPawn) p = q = CHUPROMOTED boards[0][rf][ff]; + if(CHUPROMOTED(p) < BlackPawn) p = q = CHUPROMOTED(boards[0][rf][ff]); else p = CHUDEMOTED (q = boards[0][rf][ff]); if(PieceToChar(q) == '+') gatingPiece = p; } @@ -7718,7 +7758,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(legal[y][x] == 2 || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) { if(appData.sweepSelect) { promoSweep = defaultPromoChoice; - if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece; + if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED(piece)) == '+') promoSweep = CHUPROMOTED(piece); selectFlag = 0; lastX = xPix; lastY = yPix; ReportClick("put", x, y); // extra put to prompt engine for 'choice' command Sweep(0); // Pawn that is going to promote: preview promotion piece @@ -8605,7 +8645,7 @@ HandleMachineMove (char *message, ChessProgramState *cps) ChessMove moveType; char promoChar, roar; char *p, *pv=buf1; - int machineWhite, oldError; + int oldError; char *bookHit; if(cps == &pairing && sscanf(message, "%d-%d", &savedWhitePlayer, &savedBlackPlayer) == 2) { @@ -8697,6 +8737,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } else { + int machineWhite = FALSE; + switch (gameMode) { case BeginningOfGame: /* Extra move from before last reset; ignore */ @@ -8778,7 +8820,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c, %c%c) res=%d", machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, kill2X+AAA, kill2Y+ONE, moveType); if (gameMode == TwoMachinesPlay) { - GameEnds(machineWhite ? BlackWins : WhiteWins, + GameEnds(cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins, buf1, GE_XBOARD); } return; @@ -8796,7 +8838,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if(moveType == IllegalMove) { snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c", machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0); - GameEnds(machineWhite ? BlackWins : WhiteWins, + GameEnds(cps->twoMachinesColor[0] == 'w' ? BlackWins : WhiteWins, buf1, GE_XBOARD); return; } else if(!appData.fischerCastling) @@ -9027,7 +9069,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h if(sscanf(message, "piece %s %s", buf2, buf1) == 2) { ChessSquare piece = WhitePawn; char *p=message+6, *q, *s = SUFFIXES, ID = *p; - if(*p == '+') piece = CHUPROMOTED WhitePawn, ID = *++p; + if(*p == '+') piece = CHUPROMOTED(WhitePawn), ID = *++p; if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++; piece += CharToPiece(ID & 255) - WhitePawn; if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR @@ -9046,7 +9088,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h return; } if(sscanf(message, "choice %s", promoRestrict) == 1 && promoSweep != EmptySquare) { - promoSweep = PieceToChar(forwardMostMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict)); + promoSweep = CharToPiece(currentMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict)); Sweep(0); return; } @@ -10201,8 +10243,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) ) { /* white pawn promotion */ board[toY][toX] = CharToPiece(ToUpper(promoChar)); - if(board[toY][toX] < WhiteCannon && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */ - board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); + if(board[toY][toX] < WhiteCannon && PieceToChar(PROMOTED(board[toY][toX])) == '~') /* [HGM] use shadow piece (if available) */ + board[toY][toX] = (ChessSquare) (PROMOTED(board[toY][toX])); board[fromY][fromX] = EmptySquare; } else if ((fromY >= BOARD_HEIGHT>>1) && (oldEP == toX || oldEP == EP_UNKNOWN || appData.testLegality || abs(toX - fromX) > 4) @@ -10266,8 +10308,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) ) { /* black pawn promotion */ board[toY][toX] = CharToPiece(ToLower(promoChar)); - if(board[toY][toX] < BlackCannon && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */ - board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); + if(board[toY][toX] < BlackCannon && PieceToChar(PROMOTED(board[toY][toX])) == '~') /* [HGM] use shadow piece (if available) */ + board[toY][toX] = (ChessSquare) (PROMOTED(board[toY][toX])); board[fromY][fromX] = EmptySquare; } else if ((fromY < BOARD_HEIGHT>>1) && (oldEP == toX || oldEP == EP_UNKNOWN || appData.testLegality || abs(toX - fromX) > 4) @@ -10341,10 +10383,10 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) p = (int) captured; if (p >= (int) BlackPawn) { p -= (int)BlackPawn; - if(DEMOTED p >= 0 && PieceToChar(p) == '+') { + if(DEMOTED(p) >= 0 && PieceToChar(p) == '+') { /* Restore shogi-promoted piece to its original first */ - captured = (ChessSquare) (DEMOTED captured); - p = DEMOTED p; + captured = (ChessSquare) (DEMOTED(captured)); + p = DEMOTED(p); } p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) { p = 0; captured = BlackPawn; } @@ -10352,9 +10394,9 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) board[p][BOARD_WIDTH-1] = BLACK_TO_WHITE captured; } else { p -= (int)WhitePawn; - if(DEMOTED p >= 0 && PieceToChar(p) == '+') { - captured = (ChessSquare) (DEMOTED captured); - p = DEMOTED p; + if(DEMOTED(p) >= 0 && PieceToChar(p) == '+') { + captured = (ChessSquare) (DEMOTED(captured)); + p = DEMOTED(p); } p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; } @@ -10382,13 +10424,13 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } else if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */ - board[toY][toX] = (ChessSquare) (CHUPROMOTED piece); + board[toY][toX] = (ChessSquare) (CHUPROMOTED(piece)); if(gameInfo.variant == VariantChuChess && (piece == WhiteKnight || piece == BlackKnight)) board[toY][toX] = piece + WhiteLion - WhiteKnight; // adjust Knight promotions to Lion } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar ChessSquare newPiece = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); - if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified - && pieceToChar[PROMOTED newPiece] == '~') newPiece = PROMOTED newPiece; // but promoted version available + if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified + && pieceToChar[PROMOTED(newPiece)] == '~') newPiece = PROMOTED(newPiece);// but promoted version available board[toY][toX] = newPiece; } if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) @@ -15378,7 +15420,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) case PromotePiece: if(piece >= (int)WhitePawn && piece < (int)WhiteMan || piece >= (int)BlackPawn && piece < (int)BlackMan ) { - selection = (ChessSquare) (PROMOTED piece); + selection = (ChessSquare) (PROMOTED(piece)); } else if(piece == EmptySquare) selection = WhiteSilver; else selection = (ChessSquare)((int)piece - 1); goto defaultlabel; @@ -15386,7 +15428,7 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) case DemotePiece: if(piece > (int)WhiteMan && piece <= (int)WhiteKing || piece > (int)BlackMan && piece <= (int)BlackKing ) { - selection = (ChessSquare) (DEMOTED piece); + selection = (ChessSquare) (DEMOTED(piece)); } else if(piece == EmptySquare) selection = BlackSilver; else selection = (ChessSquare)((int)piece + 1); goto defaultlabel; @@ -16955,6 +16997,7 @@ ParseOption (Option *opt, ChessProgramState *cps) 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 @@ -16977,14 +17020,17 @@ ParseOption (Option *opt, ChessProgramState *cps) } 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); @@ -17048,9 +17094,9 @@ FeatureDone (ChessProgramState *cps, int val) (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 */ @@ -17992,13 +18038,13 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) if(PieceToChar(piece) == '+') { /* [HGM] write promoted pieces as '+' (Shogi) */ *p++ = '+'; - piece = (ChessSquare)(CHUDEMOTED piece); + piece = (ChessSquare)(CHUDEMOTED(piece)); } *p++ = (piece == DarkSquare ? '*' : PieceToChar(piece)); if(*p = PieceSuffix(piece)) p++; if(p[-1] == '~') { /* [HGM] flag promoted pieces as '~' (Crazyhouse) */ - p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED piece)); + p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED(piece))); *p++ = '~'; } } @@ -18240,7 +18286,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) if(q = strchr(s, p[1])) p++; piece = CharToPiece(c + (q ? 64*(q - s + 1) : 0)); if(piece == EmptySquare) return FALSE; /* unknown piece */ - piece = (ChessSquare) (CHUPROMOTED piece ); p++; + piece = (ChessSquare) (CHUPROMOTED(piece)); p++; if(PieceToChar(piece) != '+') return FALSE; /* unpromotable piece */ } else { char c = *p++; @@ -18250,7 +18296,7 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) if(piece==EmptySquare) return FALSE; /* unknown piece */ if(*p == '~') { /* [HGM] make it a promoted piece for Crazyhouse */ - piece = (ChessSquare) (PROMOTED piece); + piece = (ChessSquare) (PROMOTED(piece)); if(PieceToChar(piece) != '~') return FALSE; /* cannot be a promoted piece */ p++; }