X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=bd641fea724a47c2012766ff35c28f13c6a11367;hb=357e76cac0dedc4522e0018b0fb49abbe879c4da;hp=46a14c7e83e65e06e1744e7052f5991fcf914e95;hpb=41ae77e8698b5b851b09681ce9b7120ccb605eb6;p=xboard.git diff --git a/backend.c b/backend.c index 46a14c7..bd641fe 100644 --- a/backend.c +++ b/backend.c @@ -957,6 +957,7 @@ InitBackEnd1() case VariantJanus: /* should work */ case VariantSuper: /* experimental */ case VariantGreat: /* experimental, requires legality testing to be off */ + case VariantSChess: /* S-Chess, should work */ break; } } @@ -3854,7 +3855,7 @@ ParseBoard12(string) int j, k, n, moveNum, white_stren, black_stren, white_time, black_time, takeback; int double_push, castle_ws, castle_wl, castle_bs, castle_bl, irrev_count; char to_play, board_chars[200]; - char move_str[500], str[500], elapsed_time[500]; + char move_str[MSG_SIZ], str[MSG_SIZ], elapsed_time[MSG_SIZ]; char black[32], white[32]; Board board; int prevMove = currentMove; @@ -3895,7 +3896,7 @@ ParseBoard12(string) &ticking); if (n < 21) { - snprintf(str, sizeof(str), _("Failed to parse board string:\n\"%s\""), string); + snprintf(str, MSG_SIZ, _("Failed to parse board string:\n\"%s\""), string); DisplayError(str, 0); return; } @@ -4344,7 +4345,7 @@ ParseBoard12(string) if(!appData.testLegality && move_str[1] != '@') { // drops never ambiguous (parser chokes on long form!) if(appData.debugMode) fprintf(debugFP, "replaced ICS move '%s' by '%s'\n", move_str, buf); - safeStrCpy(move_str, buf, sizeof(move_str)/sizeof(move_str[0])); + safeStrCpy(move_str, buf, MSG_SIZ); } valid = ParseOneMove(move_str, moveNum - 1, &moveType, &fromX, &fromY, &toX, &toY, &promoChar) @@ -5348,12 +5349,12 @@ InitPosition(redraw) if(startVariant == gameInfo.variant) // [HGM] nicks: enable nicknames in original variant SetCharTable(pieceNickName, appData.pieceNickNames); else SetCharTable(pieceNickName, "............"); + pieces = FIDEArray; switch (gameInfo.variant) { case VariantFischeRandom: shuffleOpenings = TRUE; default: - pieces = FIDEArray; break; case VariantShatranj: pieces = ShatranjArray; @@ -5381,6 +5382,10 @@ InitPosition(redraw) gameInfo.boardWidth = 10; SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); break; + case VariantSChess: + SetCharTable(pieceToChar, "PNBRQ..HEKpnbrq..hek"); + gameInfo.holdingsSize = 7; + break; case VariantJanus: pieces = JanusArray; gameInfo.boardWidth = 10; @@ -5537,6 +5542,14 @@ InitPosition(redraw) initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan; initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9; } + if( gameInfo.variant == VariantSChess ) { + initialPosition[1][0] = BlackMarshall; + initialPosition[2][0] = BlackAngel; + initialPosition[6][BOARD_WIDTH-1] = WhiteMarshall; + initialPosition[5][BOARD_WIDTH-1] = WhiteAngel; + initialPosition[1][1] = initialPosition[2][1] = + initialPosition[6][BOARD_WIDTH-2] = initialPosition[5][BOARD_WIDTH-2] = 1; + } if (appData.debugMode) { fprintf(debugFP, "shuffleOpenings = %d\n", shuffleOpenings); } @@ -6327,6 +6340,8 @@ Explode(Board board, int fromX, int fromY, int toX, int toY) return FALSE; } +ChessSquare gatingPiece = EmptySquare; // exported to front-end, for dragging + void LeftClick(ClickType clickType, int xPix, int yPix) { int x, y; @@ -6383,8 +6398,15 @@ void LeftClick(ClickType clickType, int xPix, int yPix) autoQueen = appData.alwaysPromoteToQueen; if (fromX == -1) { + gatingPiece = EmptySquare; + if (clickType != Press) { + if(dragging) { // [HGM] from-square must have been reset due to game end since last press + DragPieceEnd(xPix, yPix); dragging = 0; + DrawPosition(FALSE, NULL); + } + return; + } if(!appData.oneClick || !OnlyMove(&x, &y, FALSE)) { - if (clickType == Press) { /* First square */ if (OKToStartUserMove(x, y)) { fromX = x; @@ -6396,12 +6418,8 @@ void LeftClick(ClickType clickType, int xPix, int yPix) SetHighlights(x, y, -1, -1); } } - } else if(dragging) { // [HGM] from-square must have been reset due to game end since last press - DragPieceEnd(xPix, yPix); dragging = 0; - DrawPosition(FALSE, NULL); + return; } - return; - } } /* fromX != -1 */ @@ -6416,7 +6434,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) /* Check if clicking again on the same color piece */ fromP = boards[currentMove][fromY][fromX]; toP = boards[currentMove][y][x]; - frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom; + frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom || gameInfo.variant == VariantSChess; if ((WhitePawn <= fromP && fromP <= WhiteKing && WhitePawn <= toP && toP <= WhiteKing && !(fromP == WhiteKing && toP == WhiteRook && frc) && @@ -6434,13 +6452,19 @@ void LeftClick(ClickType clickType, int xPix, int yPix) ClearHighlights(); } if (OKToStartUserMove(x, y)) { + if(gameInfo.variant == VariantSChess && // S-Chess: back-rank piece selected after holdings means gating + (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && + y == (toP < BlackPawn ? 0 : BOARD_HEIGHT-1)) + gatingPiece = boards[currentMove][fromY][fromX]; + else gatingPiece = EmptySquare; fromX = x; fromY = y; dragging = 1; MarkTargetSquares(0); DragPieceBegin(xPix, yPix); } - return; } + if(x == fromX && y == fromY) return; // if OnlyMove altered (x,y) we go on + second = FALSE; } // ignore clicks on holdings if(x < BOARD_LEFT || x >= BOARD_RGHT) return; @@ -6456,6 +6480,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) /* Second up/down in same square; just abort move */ second = 0; fromX = fromY = -1; + gatingPiece = EmptySquare; ClearHighlights(); gotPremove = 0; ClearPremoveHighlights(); @@ -6518,7 +6543,9 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } // off-board moves should not be highlighted - if(x < 0 || x < 0) ClearHighlights(); + if(x < 0 || y < 0) ClearHighlights(); + + if(gatingPiece != EmptySquare) promoChoice = ToLower(PieceToChar(gatingPiece)); if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice)) { SetHighlights(fromX, fromY, toX, toY); @@ -7488,13 +7515,15 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats. * Look for communication commands */ if (!strncmp(message, "telluser ", 9)) { - EscapeExpand(message+9, message+9); // [HGM] esc: allow escape sequences in popup box + if(message[9] == '\\' && message[10] == '\\') + EscapeExpand(message+9, message+11); // [HGM] esc: allow escape sequences in popup box DisplayNote(message + 9); return; } if (!strncmp(message, "tellusererror ", 14)) { cps->userError = 1; - EscapeExpand(message+14, message+14); // [HGM] esc: allow escape sequences in popup box + if(message[14] == '\\' && message[15] == '\\') + EscapeExpand(message+14, message+16); // [HGM] esc: allow escape sequences in popup box DisplayError(message + 14, 0); return; } @@ -8429,21 +8458,21 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) king += (int) WhiteUnicorn - (int) WhiteKing; /* Code added by Tord: */ - /* FRC castling assumed when king captures friendly rook. */ - if (board[fromY][fromX] == WhiteKing && - board[toY][toX] == WhiteRook) { + /* 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[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; - if(toX > fromX) { + if((toX > fromX) != (piece == WhiteRook)) { board[0][BOARD_RGHT-2] = WhiteKing; board[0][BOARD_RGHT-3] = WhiteRook; } else { board[0][BOARD_LEFT+2] = WhiteKing; board[0][BOARD_LEFT+3] = WhiteRook; } - } else if (board[fromY][fromX] == BlackKing && - board[toY][toX] == BlackRook) { + } else if (board[fromY][fromX] == BlackKing && board[toY][toX] == BlackRook || + board[fromY][fromX] == BlackRook && board[toY][toX] == BlackKing) { board[fromY][fromX] = EmptySquare; board[toY][toX] = EmptySquare; - if(toX > fromX) { + if((toX > fromX) != (piece == BlackRook)) { board[BOARD_HEIGHT-1][BOARD_RGHT-2] = BlackKing; board[BOARD_HEIGHT-1][BOARD_RGHT-3] = BlackRook; } else { board[BOARD_HEIGHT-1][BOARD_LEFT+2] = BlackKing; board[BOARD_HEIGHT-1][BOARD_LEFT+3] = BlackRook; @@ -8576,10 +8605,11 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) /* [HGM] OK, so I have written it. Holdings are stored in the */ /* penultimate board files, so they are automaticlly stored */ /* in the game history. */ - if (fromY == DROP_RANK) { + if (fromY == DROP_RANK || gameInfo.variant == VariantSChess + && promoChar && piece != WhitePawn && piece != BlackPawn) { /* Delete from holdings, by decreasing count */ /* and erasing image if necessary */ - p = (int) fromX; + p = fromY == DROP_RANK ? (int) fromX : CharToPiece(piece > BlackPawn ? ToLower(promoChar) : ToUpper(promoChar)); if(p < (int) BlackPawn) { /* white drop */ p -= (int)WhitePawn; p = PieceToNumber((ChessSquare)p); @@ -8599,7 +8629,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) } } if (captured != EmptySquare && gameInfo.holdingsSize > 0 - && gameInfo.variant != VariantBughouse ) { + && gameInfo.variant != VariantBughouse && gameInfo.variant != VariantSChess ) { /* [HGM] holdings: Add to holdings, if holdings exist */ if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { // [HGM] superchess: suppress flipping color of captured pieces by reverse pre-flip @@ -8643,6 +8673,9 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[toY][toX] = EmptySquare; } } + if(gameInfo.variant == VariantSChess && promoChar != NULLCHAR && promoChar != '=' && piece != WhitePawn && piece != BlackPawn) { + board[fromY][fromX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); // S-Chess gating + } else if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */ board[toY][toX] = (ChessSquare) (PROMOTED piece); @@ -13558,6 +13591,8 @@ ReceiveFromProgram(isr, closure, message, count, error) sscanf(message, "error %c", &c)!=1 && sscanf(message, "illegal %c", &c)!=1 && sscanf(message, "tell%c", &c)!=1 && sscanf(message, "0-1 %c", &c)!=1 && sscanf(message, "1-0 %c", &c)!=1 && sscanf(message, "1/2-1/2 %c", &c)!=1 && + sscanf(message, "setboard %c", &c)!=1 && sscanf(message, "setup %c", &c)!=1 && + sscanf(message, "hint: %c", &c)!=1 && sscanf(message, "pong %c", &c)!=1 && start != '#') { quote = appData.engineComments == 2 ? "# " : "### NON-COMPLIANT! ### "; print = (appData.engineComments >= 2);