X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=892b8b63c216adb3203c927a3a4b7a11e404e4cf;hb=b56925ff216c2a794c42273aa3b59770469659a4;hp=776990427b066f125e49ad15a267cb7bc73b9ba2;hpb=f12a0a98acb97e2aa4c926bea3eddea8d1ed94da;p=xboard.git diff --git a/backend.c b/backend.c old mode 100755 new mode 100644 index 7769904..892b8b6 --- a/backend.c +++ b/backend.c @@ -5,7 +5,7 @@ * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009 Free Software Foundation, Inc. + * 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * * Enhancements Copyright 2005 Alessandro Scotti * @@ -187,8 +187,9 @@ void DisplayMove P((int moveNumber)); void ParseGameHistory P((char *game)); void ParseBoard12 P((char *string)); +void KeepAlive P((void)); void StartClocks P((void)); -void SwitchClocks P((void)); +void SwitchClocks P((int nr)); void StopClocks P((void)); void ResetClocks P((void)); char *PGNDate P((void)); @@ -242,6 +243,7 @@ char endingGame = 0; /* [HGM] crash: flag to prevent recursion of GameEnds() int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */ VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */ int lastIndex = 0; /* [HGM] autoinc: last game/position used in match mode */ +Boolean connectionAlive;/* [HGM] alive: ICS connection status from probing */ int opponentKibitzes; int lastSavedGame; /* [HGM] save: ID of game */ char chatPartner[MAX_CHAT][MSG_SIZ]; /* [HGM] chat: list of chatting partners */ @@ -353,6 +355,7 @@ PosFlags(index) case VariantNoCastle: case VariantShatranj: case VariantCourier: + case VariantMakruk: flags &= ~F_ALL_CASTLE_OK; break; default: @@ -474,11 +477,11 @@ ChessSquare KnightmateArray[2][BOARD_SIZE] = { BlackUnicorn, BlackBishop, BlackMan, BlackRook } }; -ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] Queen side differs from King side */ - { WhiteCannon, WhiteNightrider, WhiteAlfil, WhiteQueen, +ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] white and black different armies! */ + { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, WhiteBishop, WhiteKnight, WhiteRook }, - { BlackCannon, BlackNightrider, BlackAlfil, BlackQueen, - BlackKing, BlackBishop, BlackKnight, BlackRook } + { BlackLance, BlackAlfil, BlackMarshall, BlackAngel, + BlackKing, BlackMarshall, BlackAlfil, BlackLance } }; ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */ @@ -488,6 +491,13 @@ ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatra BlackFerz, BlackAlfil, BlackKnight, BlackRook } }; +ChessSquare makrukArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */ + { WhiteRook, WhiteKnight, WhiteMan, WhiteKing, + WhiteFerz, WhiteMan, WhiteKnight, WhiteRook }, + { BlackRook, BlackKnight, BlackMan, BlackFerz, + BlackKing, BlackMan, BlackKnight, BlackRook } +}; + #if (BOARD_SIZE>=10) ChessSquare ShogiArray[2][BOARD_SIZE] = { @@ -743,7 +753,7 @@ InitBackEnd1() /* [HGM] time odds: set factor for each machine */ first.timeOdds = appData.firstTimeOdds; second.timeOdds = appData.secondTimeOdds; - { int norm = 1; + { float norm = 1; if(appData.timeOddsMode) { norm = first.timeOdds; if(norm > second.timeOdds) norm = second.timeOdds; @@ -873,6 +883,7 @@ InitBackEnd1() case VariantAtomic: /* should work except for win condition */ case Variant3Check: /* should work except for win condition */ case VariantShatranj: /* should work except for all win conditions */ + case VariantMakruk: /* should work except for daw countdown */ case VariantBerolina: /* might work if TestLegality is off */ case VariantCapaRandom: /* should work */ case VariantJanus: /* should work */ @@ -1097,6 +1108,8 @@ InitBackEnd3 P((void)) AddInputSource(icsPR, FALSE, read_from_ics, &telnetISR); fromUserISR = AddInputSource(NoProc, FALSE, read_from_player, &fromUserISR); + if(appData.keepAlive) // [HGM] alive: schedule sending of dummy 'date' command + ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000); } else if (appData.noChessProgram) { SetNCPMode(); } else { @@ -1417,6 +1430,8 @@ read_from_player(isr, closure, message, count, error) void KeepAlive() { // [HGM] alive: periodically send dummy (date) command to ICS to prevent time-out + if(!connectionAlive) DisplayFatalError("No response from ICS", 0, 1); + connectionAlive = FALSE; // only sticks if no response to 'date' command. SendToICS("date\n"); if(appData.keepAlive) ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000); } @@ -2042,7 +2057,7 @@ read_from_ics(isr, closure, data, count, error) int count; int error; { -#define BUF_SIZE 8192 +#define BUF_SIZE (16*1024) /* overflowed at 8K with "inchannel 1" on FICS? */ #define STARTED_NONE 0 #define STARTED_MOVES 1 #define STARTED_BOARD 2 @@ -2071,6 +2086,8 @@ read_from_ics(isr, closure, data, count, error) char talker[MSG_SIZ]; // [HGM] chat int channel; + connectionAlive = TRUE; // [HGM] alive: I think, therefore I am... + if (appData.debugMode) { if (!error) { fprintf(debugFP, " MSG_SIZ - 30) // defuse unreasonably long input { parse_pos = MSG_SIZ-30; parse[parse_pos - 1] = '\n'; } parse[parse_pos] = NULLCHAR; // try to be smart: if it does not look like search info, it should go to // ICS interaction window after all, not to engine-output window. - for(i=0; i= '0' && parse[i] <= '9'); - nrAlph += (parse[i] >= 'a' && parse[i] <= 'z'); - nrAlph += (parse[i] >= 'A' && parse[i] <= 'Z'); + for(j=0; j= '0' && parse[j] <= '9'); + nrAlph += (parse[j] >= 'a' && parse[j] <= 'z'); + nrAlph += (parse[j] >= 'A' && parse[j] <= 'Z'); } if(nrAlph < 9*nrDigit) { // if more than 10% digit we assume search info int depth=0; float score; @@ -2332,10 +2351,11 @@ read_from_ics(isr, closure, data, count, error) sprintf(tmp, _("your opponent kibitzes: %s"), parse); SendToPlayer(tmp, strlen(tmp)); } + next_out = i+1; // [HGM] suppress printing in ICS window } started = STARTED_NONE; } else { - /* Don't match patterns against characters in chatter */ + /* Don't match patterns against characters in comment */ i++; continue; } @@ -2347,6 +2367,7 @@ read_from_ics(isr, closure, data, count, error) continue; } started = STARTED_NONE; + if(suppressKibitz) next_out = i+1; } /* Kludge to deal with rcmd protocol */ @@ -2417,10 +2438,12 @@ read_from_ics(isr, closure, data, count, error) if (appData.autoKibitz && started == STARTED_NONE && !appData.icsEngineAnalyze && // [HGM] [DM] ICS analyze (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || gameMode == IcsObserving)) { - if(looking_at(buf, &i, "* kibitzes: ") && + if((looking_at(buf, &i, "\n* kibitzes: ") || looking_at(buf, &i, "* kibitzes: ")) && (StrStr(star_match[0], gameInfo.white) == star_match[0] || StrStr(star_match[0], gameInfo.black) == star_match[0] )) { // kibitz of self or opponent suppressKibitz = TRUE; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); + next_out = i; if((StrStr(star_match[0], gameInfo.white) == star_match[0] && (gameMode == IcsPlayingWhite)) || (StrStr(star_match[0], gameInfo.black) == star_match[0] @@ -2435,9 +2458,18 @@ read_from_ics(isr, closure, data, count, error) } continue; } else - if(looking_at(buf, &i, "kibitzed to")) { // suppress the acknowledgements of our own autoKibitz - started = STARTED_CHATTER; - suppressKibitz = TRUE; + if((looking_at(buf, &i, "\nkibitzed to *\n") || looking_at(buf, &i, "kibitzed to *\n") || + looking_at(buf, &i, "\n(kibitzed to *\n") || looking_at(buf, &i, "(kibitzed to *\n")) + && atoi(star_match[0])) { + // suppress the acknowledgements of our own autoKibitz + char *p; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); + if(p = strchr(star_match[0], ' ')) p[1] = NULLCHAR; // clip off "players)" on FICS + SendToPlayer(star_match[0], strlen(star_match[0])); + if(looking_at(buf, &i, "*% ")) // eat prompt + suppressKibitz = FALSE; + next_out = i; + continue; } } // [HGM] kibitz: end of patch @@ -2448,7 +2480,9 @@ read_from_ics(isr, closure, data, count, error) if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") || looking_at(buf, &i, "* whispers:") || looking_at(buf, &i, "*(*):") && (sscanf(star_match[1], "%d", &channel),1) || - looking_at(buf, &i, "*(*)(*):") && sscanf(star_match[2], "%d", &channel) == 1 )) { + looking_at(buf, &i, "*(*)(*):") && (sscanf(star_match[2], "%d", &channel),1) || + looking_at(buf, &i, "*(*)(*)(*):") && (sscanf(star_match[3], "%d", &channel),1) || + looking_at(buf, &i, "*(*)(*)(*)(*):") && sscanf(star_match[4], "%d", &channel) == 1 )) { int p; sscanf(star_match[0], "%[^(]", talker+1); // strip (C) or (U) off ICS handle chattingPartner = -1; @@ -2456,14 +2490,14 @@ read_from_ics(isr, closure, data, count, error) if(channel >= 0) // channel broadcast; look if there is a chatbox for this channel for(p=0; p 0 && buf[oldi-1] == '\n') oldi--; + if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out); started = STARTED_COMMENT; parse_pos = 0; parse[0] = NULLCHAR; - savingComment = TRUE; + savingComment = 3 + chattingPartner; // counts as TRUE suppressKibitz = TRUE; + continue; } } // [HGM] chat: end of patch @@ -2670,6 +2707,8 @@ read_from_ics(isr, closure, data, count, error) memcpy(parse, &buf[oldi], parse_pos); parse[parse_pos] = NULLCHAR; started = STARTED_COMMENT; + if(savingComment >= 3) // [HGM] chat: continuation of line for chat box + chattingPartner = savingComment - 3; // kludge to remember the box } else { started = STARTED_CHATTER; } @@ -2837,7 +2876,9 @@ read_from_ics(isr, closure, data, count, error) if (looking_at(buf, &i, "% ") || ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE) && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book + if(suppressKibitz) next_out = i; savingComment = FALSE; + suppressKibitz = 0; switch (started) { case STARTED_MOVES: case STARTED_MOVES_NOHIDE: @@ -3030,10 +3071,10 @@ read_from_ics(isr, closure, data, count, error) looking_at(buf, &i, "It is not your move")) { /* Illegal move */ if (ics_user_moved && forwardMostMove > backwardMostMove) { // only backup if we already moved - currentMove = --forwardMostMove; + currentMove = forwardMostMove-1; DisplayMove(currentMove - 1); /* before DMError */ DrawPosition(FALSE, boards[currentMove]); - SwitchClocks(); + SwitchClocks(forwardMostMove-1); // [HGM] race DisplayBothClocks(); } DisplayMoveError(_("Illegal move (rejected by ICS)")); // [HGM] but always relay error msg @@ -3134,6 +3175,7 @@ read_from_ics(isr, closure, data, count, error) strncmp(why, "Continuing ", 11) == 0) { gs_gamenum = gamenum; strcpy(gs_kind, strchr(why, ' ') + 1); + VariantSwitch(boards[currentMove], StringToVariant(gs_kind)); // [HGM] variantswitch: even before we get first board #if ZIPPY if (appData.zippyPlay) { ZippyGameStart(whitename, blackname); @@ -3263,6 +3305,7 @@ read_from_ics(isr, closure, data, count, error) while(looking_at(buf, &i, "\n")); // [HGM] skip empty lines if (looking_at(buf, &i, "*% ")) { savingComment = FALSE; + suppressKibitz = 0; } } next_out = i; @@ -3332,6 +3375,7 @@ read_from_ics(isr, closure, data, count, error) if (looking_at(buf, &i, "*% ")) { if(strchr(star_match[0], 7)) SendToPlayer("\007", 1); // Bell(); // FICS fuses bell for next board with prompt in zh captures savingComment = FALSE; + suppressKibitz = 0; } next_out = i; } @@ -3341,12 +3385,13 @@ read_from_ics(isr, closure, data, count, error) i++; /* skip unparsed character and loop back */ } - if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz suppress printing in ICS interaction window - started != STARTED_HOLDINGS && i > next_out) { - SendToPlayer(&buf[next_out], i - next_out); + if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz +// started != STARTED_HOLDINGS && i > next_out) { // [HGM] should we compare to leftover_start in stead of i? +// SendToPlayer(&buf[next_out], i - next_out); + started != STARTED_HOLDINGS && leftover_start > next_out) { + SendToPlayer(&buf[next_out], leftover_start - next_out); next_out = i; } - suppressKibitz = FALSE; // [HGM] kibitz: has done its duty in if-statement above leftover_len = buf_len - leftover_start; /* if buffer ends with something we couldn't parse, @@ -3699,6 +3744,11 @@ ParseBoard12(string) for(k=BOARD_LEFT; k=backwardMostMove; i-- ) - fprintf(debugFP, "%d ep=%d\n", i, epStatus[i]); - - } /* Check for rep-draws */ count = 0; @@ -6639,9 +6689,9 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. gameMode = EditGame; ModeHighlight(); } - currentMove = --forwardMostMove; + currentMove = forwardMostMove-1; DisplayMove(currentMove-1); /* before DisplayMoveError */ - SwitchClocks(); + SwitchClocks(forwardMostMove-1); // [HGM] race DisplayBothClocks(); sprintf(buf1, _("Illegal move \"%s\" (rejected by %s chess program)"), parseList[currentMove], cps->which); @@ -6932,7 +6982,12 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. /* [AS] Negate score if machine is playing black and reporting absolute scores */ if( cps->scoreIsAbsolute && - ((gameMode == MachinePlaysBlack) || (gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b')) ) + ( gameMode == MachinePlaysBlack || + gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b' || + gameMode == IcsPlayingBlack || // [HGM] also add other situations where engine should report black POV + (gameMode == AnalyzeMode || gameMode == AnalyzeFile || gameMode == IcsObserving && appData.icsEngineAnalyze) && + !WhiteOnMove(currentMove) + ) ) { curscore = -curscore; } @@ -7352,6 +7407,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) char *ep; { ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0; + int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1; /* [HGM] compute & store e.p. status and castling rights for new position */ /* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */ @@ -7398,7 +7454,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) } /* [HGM] In Shatranj and Courier all promotions are to Ferz */ - if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier) + if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk) && promoChar != 0) promoChar = PieceToChar(WhiteFerz); if (fromX == toX && fromY == toY) return; @@ -7449,7 +7505,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) board[toY][toX+1] = board[fromY][BOARD_LEFT]; board[fromY][BOARD_LEFT] = EmptySquare; } else if (board[fromY][fromX] == WhitePawn - && toY == BOARD_HEIGHT-1 + && toY >= BOARD_HEIGHT-promoRank && gameInfo.variant != VariantXiangqi ) { /* white pawn promotion */ @@ -7513,13 +7569,13 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board, castling, ep) board[fromY][0] = EmptySquare; board[toY][2] = BlackRook; } else if (board[fromY][fromX] == BlackPawn - && toY == 0 + && toY < promoRank && gameInfo.variant != VariantXiangqi ) { /* black pawn promotion */ - board[0][toX] = CharToPiece(ToLower(promoChar)); - if (board[0][toX] == EmptySquare) { - board[0][toX] = BlackQueen; + board[toY][toX] = CharToPiece(ToLower(promoChar)); + if (board[toY][toX] == EmptySquare) { + board[toY][toX] = BlackQueen; } if(gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */ @@ -7714,8 +7770,8 @@ MakeMove(fromX, fromY, toX, toY, promoChar) {int i; for(i=0; i= GE_ENGINE1)) { /* If we are playing on ICS, the server decides when the game is over, but the engine can offer to draw, claim @@ -11368,7 +11426,8 @@ EditPositionMenuEvent(selection, x, y) case BlackQueen: if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantXiangqi || - gameInfo.variant == VariantCourier ) + gameInfo.variant == VariantCourier || + gameInfo.variant == VariantMakruk ) selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz); goto defaultlabel; @@ -12605,7 +12664,7 @@ SendTimeRemaining(cps, machineWhite) /* [HGM] translate opponent's time by time-odds factor */ otime = (otime * cps->other->timeOdds) / cps->timeOdds; if (appData.debugMode) { - fprintf(debugFP, "time odds: %d %d \n", cps->timeOdds, cps->other->timeOdds); + fprintf(debugFP, "time odds: %f %f \n", cps->timeOdds, cps->other->timeOdds); } if (time <= 0) time = 1; @@ -13340,7 +13399,7 @@ DecrementClocks() from the color that is *not* on move now. */ void -SwitchClocks() +SwitchClocks(int newMoveNr) { long lastTickLength; TimeMark now; @@ -13350,7 +13409,7 @@ SwitchClocks() if (StopClockTimer() && appData.clockMode) { lastTickLength = SubtractTimeMarks(&now, &tickStartTM); - if (WhiteOnMove(forwardMostMove)) { + if (!WhiteOnMove(forwardMostMove)) { if(blackNPS >= 0) lastTickLength = 0; blackTimeRemaining -= lastTickLength; /* [HGM] PGNtime: save time for PGN file if engine did not give it */ @@ -13367,6 +13426,7 @@ SwitchClocks() } flagged = CheckFlags(); } + forwardMostMove = newMoveNr; // [HGM] race: change stm when no timer interrupt scheduled CheckTimeControl(); if (flagged || !appData.clockMode) return; @@ -13686,7 +13746,7 @@ PositionToFEN(move, overrideCastling) *p++ = ' '; if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines - while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; + while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p; } else { if(nrCastlingRights) { q = p; @@ -13723,7 +13783,7 @@ PositionToFEN(move, overrideCastling) } if(gameInfo.variant != VariantShogi && gameInfo.variant != VariantXiangqi && - gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier ) { + gameInfo.variant != VariantShatranj && gameInfo.variant != VariantCourier && gameInfo.variant != VariantMakruk ) { /* En passant target square */ if (move > backwardMostMove) { fromX = moveList[move - 1][0] - AAA; @@ -13898,10 +13958,12 @@ ParseFEN(board, blackPlaysFirst, fen) } /* assume possible unless obviously impossible */ if(initialRights[0]>=0 && board[castlingRank[0]][initialRights[0]] != WhiteRook) FENcastlingRights[0] = -1; if(initialRights[1]>=0 && board[castlingRank[1]][initialRights[1]] != WhiteRook) FENcastlingRights[1] = -1; - if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1; + if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteUnicorn + && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1; if(initialRights[3]>=0 && board[castlingRank[3]][initialRights[3]] != BlackRook) FENcastlingRights[3] = -1; if(initialRights[4]>=0 && board[castlingRank[4]][initialRights[4]] != BlackRook) FENcastlingRights[4] = -1; - if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1; + if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackUnicorn + && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1; FENrulePlies = 0; while(*p==' ') p++; @@ -13922,9 +13984,15 @@ ParseFEN(board, blackPlaysFirst, fen) if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i; if(board[0 ][i] == WhiteKing) whiteKingFile = i; } + if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate) + whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // scanning fails in these variants + if(whiteKingFile<0 || board[0][whiteKingFile]!=WhiteUnicorn + && board[0][whiteKingFile]!=WhiteKing) whiteKingFile = -1; + if(blackKingFile<0 || board[BOARD_HEIGHT-1][blackKingFile]!=BlackUnicorn + && board[BOARD_HEIGHT-1][blackKingFile]!=BlackKing) blackKingFile = -1; switch(c) { case'K': - for(i=BOARD_RGHT-1; board[0][i]!=WhiteRook && i>whiteKingFile; i--); + for(i=BOARD_RGHT-1; i>whiteKingFile && board[0][i]!=WhiteRook; i--); FENcastlingRights[0] = i != whiteKingFile ? i : -1; FENcastlingRights[2] = whiteKingFile; break; @@ -13934,7 +14002,7 @@ ParseFEN(board, blackPlaysFirst, fen) FENcastlingRights[2] = whiteKingFile; break; case'k': - for(i=BOARD_RGHT-1; board[BOARD_HEIGHT-1][i]!=BlackRook && i>blackKingFile; i--); + for(i=BOARD_RGHT-1; i>blackKingFile && board[BOARD_HEIGHT-1][i]!=BlackRook; i--); FENcastlingRights[3] = i != blackKingFile ? i : -1; FENcastlingRights[5] = blackKingFile; break; @@ -13971,6 +14039,8 @@ ParseFEN(board, blackPlaysFirst, fen) } } } + for(i=0; i= 0) initialRights[i] = FENcastlingRights[i]; if (appData.debugMode) { fprintf(debugFP, "FEN castling rights:"); for(i=0; i