X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=8c5ac409722b9380efc11ebfac140bf70cbc3194;hb=6b19d6b88b12d1e1493d778d140e99c4f751faff;hp=605940e4443c5808d927b928c849beec46e74ed0;hpb=89f4b438a9bc3ed2b2b2bd79f22a1a6af06e9bcb;p=xboard.git diff --git a/backend.c b/backend.c index 605940e..8c5ac40 100644 --- a/backend.c +++ b/backend.c @@ -295,7 +295,7 @@ ChessSquare promoSweep = EmptySquare, defaultPromoChoice; int promoDefaultAltered; int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */ static int initPing = -1; -static Boolean pieceDefs; +int border; /* [HGM] width of board rim, needed to size seek graph */ /* States for ics_getting_history */ #define H_FALSE 0 @@ -1201,6 +1201,11 @@ InitBackEnd1 () DisplayFatalError(buf, 0, 2); return; + case VariantNormal: /* definitely works! */ + if(strcmp(appData.variant, "normal") && appData.chessProgram) { // [HGM] hope this is an engine-defined variant + safeStrCpy(engineVariant, appData.variant, MSG_SIZ); + return; + } case VariantXiangqi: /* [HGM] repetition rules not implemented */ case VariantFairy: /* [HGM] TestLegality definitely off! */ case VariantGothic: /* [HGM] should work */ @@ -1213,7 +1218,6 @@ InitBackEnd1 () case VariantFalcon: /* [HGM] untested */ case VariantCrazyhouse: /* holdings not shown, ([HGM] fixed that!) offboard interposition not understood */ - case VariantNormal: /* definitely works! */ case VariantWildCastle: /* pieces not automatically shuffled */ case VariantNoCastle: /* pieces not automatically shuffled */ case VariantFischeRandom: /* [HGM] works and shuffles pieces */ @@ -2717,8 +2721,8 @@ DrawSeekGraph () { int i; if(!seekGraphUp) return FALSE; - h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap; - w = BOARD_WIDTH * (squareSize + lineGap) + lineGap; + h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap + 2*border; + w = BOARD_WIDTH * (squareSize + lineGap) + lineGap + 2*border; DrawSeekBackground(0, 0, w, h); DrawSeekAxis(hMargin, h-1-vMargin, w-5, h-1-vMargin); @@ -5324,6 +5328,7 @@ UploadGameEvent () } int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove +int legNr = 1; void CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7]) @@ -6103,7 +6108,7 @@ InitPosition (int redraw) case VariantFalcon: pieces = FalconArray; gameInfo.boardWidth = 10; - SetCharTable(pieceToChar, "PNBRQ.............FKpnbrq.............fk"); + SetCharTable(pieceToChar, "PNBRQ............FKpnbrq............fk"); break; case VariantXiangqi: pieces = XiangqiArray; @@ -6986,7 +6991,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar) // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings - while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; + while(PieceToChar(fromX) == '.' || PieceToChar(fromX) == '+' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; fromY = DROP_RANK; } @@ -7259,7 +7264,7 @@ Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VO { typedef char Markers[BOARD_RANKS][BOARD_FILES]; Markers *m = (Markers *) closure; - if(rf == fromY && ff == fromX && (killX < 0 && !(rt == rf && ft == ff) || abs(ft-killX) < 2 && abs(rt-killY) < 2)) + if(rf == fromY && ff == fromX && (killX < 0 ? !(rt == rf && ft == ff) && legNr & 1 : rt == killY && ft == killX || legNr & 2)) (*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare || kind == WhiteCapturesEnPassant || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0), legal[rt][ft] = 1; @@ -8873,7 +8878,6 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h s = 8 + strlen(buf), buf[s-9] = NULLCHAR, SetCharTable(pieceToChar, buf); ASSIGN(appData.pieceToCharTable, buf); } - if(startedFromSetupPosition) return; dummy = sscanf(message+s, "%dx%d+%d_%s", &w, &h, &hand, varName); if(dummy >= 3) { while(message[s] && message[s++] != ' '); @@ -8883,8 +8887,10 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h 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 + startedFromSetupPosition = FALSE; } } + if(startedFromSetupPosition) return; ParseFEN(boards[0], &dummy, message+s, FALSE); DrawPosition(TRUE, boards[0]); startedFromSetupPosition = TRUE; @@ -8893,9 +8899,15 @@ 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=buf2; - if(cps != &first || appData.testLegality) return; if(*p == '+') piece = CHUPROMOTED WhitePawn, p++; piece += CharToPiece(*p) - WhitePawn; + if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR + /* always accept definition of */ && piece != WhiteFalcon && piece != BlackFalcon + /* wild-card pieces. */ && piece != WhiteCobra && piece != BlackCobra + /* For variants we don't have */ && gameInfo.variant != VariantBerolina + /* correct rules for, we cannot */ && gameInfo.variant != VariantCylinder + /* enforce legality on our own! */ && gameInfo.variant != VariantUnknown + && gameInfo.variant != VariantFairy ) return; if(piece < EmptySquare) { pieceDefs = TRUE; ASSIGN(pieceDesc[piece], buf1); @@ -9971,6 +9983,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) /* FRC castling assumed when king captures friendly rook. [HGM] or RxK for S-Chess */ if (board[fromY][fromX] == WhiteKing && board[toY][toX] == WhiteRook || board[fromY][fromX] == WhiteRook && board[toY][toX] == WhiteKing) { + board[EP_STATUS] = EP_NONE; // capture was fake! board[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; if((toX > fromX) != (piece == WhiteRook)) { @@ -9980,6 +9993,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } } else if (board[fromY][fromX] == BlackKing && board[toY][toX] == BlackRook || board[fromY][fromX] == BlackRook && board[toY][toX] == BlackKing) { + board[EP_STATUS] = EP_NONE; board[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; if((toX > fromX) != (piece == BlackRook)) { @@ -10143,8 +10157,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) p = (int) captured; if (p >= (int) BlackPawn) { p -= (int)BlackPawn; - if(gameInfo.variant == VariantShogi && DEMOTED p >= 0) { - /* in Shogi restore piece to its original first */ + if(DEMOTED p >= 0 && PieceToChar(p) == '+') { + /* Restore shogi-promoted piece to its original first */ captured = (ChessSquare) (DEMOTED captured); p = DEMOTED p; } @@ -10154,7 +10168,7 @@ 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(gameInfo.variant == VariantShogi && DEMOTED p >= 0) { + if(DEMOTED p >= 0 && PieceToChar(p) == '+') { captured = (ChessSquare) (DEMOTED captured); p = DEMOTED p; } @@ -10482,7 +10496,19 @@ InitChessProgram (ChessProgramState *cps, int setup) b = SupportedVariant(cps->variants, gameInfo.variant, gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->protocolVersion, cps->tidy); if (b == NULL) { - DisplayFatalError(variantError, 0, 1); + VariantClass v; + char c, *q = cps->variants, *p = strchr(q, ','); + if(p) *p = NULLCHAR; + v = StringToVariant(q); + DisplayError(variantError, 0); + if(v != VariantUnknown && cps == &first) { + int w, h, s; + if(sscanf(q, "%dx%d+%d_%c", &w, &h, &s, &c) == 4) // get size overrides the engine needs with it (if any) + appData.NrFiles = w, appData.NrRanks = h, appData.holdingsSize = s, q = strchr(q, '_') + 1; + ASSIGN(appData.variant, q); + Reset(TRUE, FALSE); + } + if(p) *p = ','; return; } @@ -14641,8 +14667,10 @@ TwoMachinesEvent P((void)) if(!SupportedVariant(second.variants, gameInfo.variant, gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, second.protocolVersion, second.tidy)) { - startingEngine = FALSE; + startingEngine = matchMode = FALSE; DisplayError("second engine does not play this", 0); + gameMode = TwoMachinesPlay; ModeHighlight(); // Needed to make sure menu item is unchecked + EditGameEvent(); // switch back to EditGame mode return; } @@ -15500,6 +15528,7 @@ ForwardInner (int target) seekGraphUp = FALSE; MarkTargetSquares(1); + fromX = fromY = killX = killY = -1; // [HGM] abort any move entry in progress if (gameMode == PlayFromGameFile && !pausing) PauseEvent(); @@ -15618,6 +15647,7 @@ BackwardInner (int target) if (gameMode == EditPosition) return; seekGraphUp = FALSE; MarkTargetSquares(1); + fromX = fromY = killX = killY = -1; // [HGM] abort any move entry in progress if (currentMove <= backwardMostMove) { ClearHighlights(); DrawPosition(full_redraw, boards[currentMove]); @@ -17797,8 +17827,17 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p; } else { if(nrCastlingRights) { + int handW=0, handB=0; + if(gameInfo.variant == VariantSChess) { // for S-Chess, all virgin backrank pieces must be listed + for(i=0; i=BOARD_LEFT; i--) + if(boards[move][VIRGIN][i] & VIRGIN_W) *p++ = i + AAA + 'A' - 'a'; + } else { /* [HGM] write directly from rights */ if(boards[move][CASTLING][2] != NoRights && boards[move][CASTLING][0] != NoRights ) @@ -17806,12 +17845,18 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) if(boards[move][CASTLING][2] != NoRights && boards[move][CASTLING][1] != NoRights ) *p++ = boards[move][CASTLING][1] + AAA + 'A' - 'a'; + } + if(handB) { + for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) + if(boards[move][VIRGIN][i] & VIRGIN_B) *p++ = i + AAA; + } else { if(boards[move][CASTLING][5] != NoRights && boards[move][CASTLING][3] != NoRights ) *p++ = boards[move][CASTLING][3] + AAA; if(boards[move][CASTLING][5] != NoRights && boards[move][CASTLING][4] != NoRights ) *p++ = boards[move][CASTLING][4] + AAA; + } } else { /* [HGM] write true castling rights */ @@ -17821,8 +17866,7 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) boards[move][CASTLING][2] != NoRights ) k = 1, *p++ = 'K'; q = (boards[move][CASTLING][1] == BOARD_LEFT && boards[move][CASTLING][2] != NoRights ); - if(gameInfo.variant == VariantSChess) { // for S-Chess, indicate all vrgin backrank pieces - for(i=j=0; i=BOARD_LEFT+q && j; i--) if((boards[move][0][i] != WhiteKing || k+q == 0) && boards[move][VIRGIN][i] & VIRGIN_W) *p++ = i + AAA + 'A' - 'a'; @@ -17833,8 +17877,7 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) boards[move][CASTLING][5] != NoRights ) k = 1, *p++ = 'k'; q = (boards[move][CASTLING][4] == BOARD_LEFT && boards[move][CASTLING][5] != NoRights ); - if(gameInfo.variant == VariantSChess) { - for(i=j=0; i=BOARD_LEFT+q && j; i--) if((boards[move][BOARD_HEIGHT-1][i] != BlackKing || k+q == 0) && boards[move][VIRGIN][i] & VIRGIN_B) *p++ = i + AAA;