X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=a4f78524d57585c59b6af641ba345a26d530cf02;hb=d82d80274f7fb7c07dcf12ba873bb4c842279171;hp=8a47479ff637f2c1d2aa1a9fd72f72adb0f3203e;hpb=ff23924264802924788f2a15c73a8d058e90432e;p=xboard.git diff --git a/backend.c b/backend.c index 8a47479..a4f7852 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) @@ -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))); @@ -5547,6 +5556,7 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro *toX = currentMoveString[2] - AAA; *toY = currentMoveString[3] - ONE; *promoChar = currentMoveString[4]; + if(*promoChar == ';') *promoChar = NULLCHAR; if (*fromX < BOARD_LEFT || *fromX >= BOARD_RGHT || *fromY < 0 || *fromY >= BOARD_HEIGHT || *toX < BOARD_LEFT || *toX >= BOARD_RGHT || *toY < 0 || *toY >= BOARD_HEIGHT) { if (appData.debugMode) { @@ -5994,7 +6004,7 @@ 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 != '^' && *s != '*' && !strchr(escapes, *s)) - 2*(*s == '='), s++; return n; } @@ -6003,28 +6013,58 @@ 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, offs, j = 0; /* [HGM] Accept even length from 12 to 88 */ for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.'; for( i=offs=0; i= 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; @@ -7035,11 +7074,9 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) return; } else if (toX >= 0 && toY >= 0) { 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]); - else p = CHUDEMOTED (q = boards[0][rf][ff]); - if(PieceToChar(q) == '+') gatingPiece = p; + ChessSquare p = boards[0][rf][ff]; + if(PieceToChar(p) == '+') gatingPiece = CHUDEMOTED(p); else + if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p); } boards[0][toY][toX] = boards[0][fromY][fromX]; if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings @@ -7055,6 +7092,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) } } else boards[0][fromY][fromX] = gatingPiece; + ClearHighlights(); DrawPosition(FALSE, boards[currentMove]); return; } @@ -7752,6 +7790,8 @@ LeftClick (ClickType clickType, int xPix, int yPix) ClearHighlights(); } #endif + if(PieceToChar(CHUPROMOTED(boards[currentMove][fromY][fromX])) == '+') + defaultPromoChoice = CHUPROMOTED(boards[currentMove][fromY][fromX]); if(gameInfo.variant == VariantChuChess && piece != WhitePawn && piece != BlackPawn) defaultPromoChoice = piece; if(marker[y][x] == 5) { // [HGM] lion: this was the release of a to-click or drag on a cyan square dragging *= 2; // flag button-less dragging if we are dragging @@ -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) @@ -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; } @@ -13068,7 +13110,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList) return FALSE; } CopyBoard(boards[0], initial_position); - if(*engineVariant) // [HGM] for now, assume FEN in engine-defined variant game is default initial position + if(*engineVariant || gameInfo.variant == VariantFairy) // [HGM] for now, assume FEN in engine-defined variant game is default initial position CopyBoard(initialPosition, initial_position); if (blackPlaysFirst) { currentMove = forwardMostMove = backwardMostMove = 1; @@ -16238,7 +16280,7 @@ PrintPosition (FILE *fp, int move) for (i = BOARD_HEIGHT - 1; i >= 0; i--) { for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { char c = PieceToChar(boards[move][i][j]); - fputc(c == 'x' ? '.' : c, fp); + fputc(c == '?' ? '.' : c, fp); fputc(j == BOARD_RGHT - 1 ? '\n' : ' ', fp); } } @@ -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 */