X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=21562ab8318bb609e6ba3082d8dd1c6aac56adb0;hb=56310c5b198bc521e0a715377c68378b7bcf10a5;hp=f028af444d38b2a135e3ccb2ee67f56e0c9948da;hpb=cde66749ec8a0b3c823bbc7aa3818b86821514ec;p=xboard.git diff --git a/backend.c b/backend.c index f028af4..21562ab 100644 --- a/backend.c +++ b/backend.c @@ -396,6 +396,7 @@ PosFlags(index) case VariantShatranj: case VariantCourier: case VariantMakruk: + case VariantGrand: flags &= ~F_ALL_CASTLE_OK; break; default: @@ -599,6 +600,13 @@ ChessSquare JanusArray[2][BOARD_FILES] = { BlackQueen, BlackBishop, BlackKnight, BlackAngel, BlackRook } }; +ChessSquare GrandArray[2][BOARD_FILES] = { + { EmptySquare, WhiteKnight, WhiteBishop, WhiteQueen, WhiteKing, + WhiteMarshall, WhiteAngel, WhiteBishop, WhiteKnight, EmptySquare }, + { EmptySquare, BlackKnight, BlackBishop, BlackQueen, BlackKing, + BlackMarshall, BlackAngel, BlackBishop, BlackKnight, EmptySquare } +}; + #ifdef GOTHIC ChessSquare GothicArray[2][BOARD_FILES] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall, @@ -1112,13 +1120,14 @@ 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 VariantMakruk: /* should work except for draw countdown */ case VariantBerolina: /* might work if TestLegality is off */ case VariantCapaRandom: /* should work */ case VariantJanus: /* should work */ case VariantSuper: /* experimental */ case VariantGreat: /* experimental, requires legality testing to be off */ case VariantSChess: /* S-Chess, should work */ + case VariantGrand: /* should work */ case VariantSpartan: /* should work */ break; } @@ -4641,8 +4650,8 @@ ParseBoard12(string) safeStrCpy(moveList[moveNum - 1], currentMoveString, sizeof(moveList[moveNum - 1])/sizeof(moveList[moveNum - 1][0])); strcat(moveList[moveNum - 1], "\n"); - if(gameInfo.holdingsWidth && !appData.disguise && gameInfo.variant != VariantSuper - && gameInfo.variant != VariantGreat) // inherit info that ICS does not give from previous board + if(gameInfo.holdingsWidth && !appData.disguise && gameInfo.variant != VariantSuper && gameInfo.variant != VariantGreat + && gameInfo.variant != VariantGrand) // inherit info that ICS does not give from previous board for(k=0; k 10) { // [HGM] big: convert ranks to double-digit where needed + if(moveList[moveNum][1] == '@' && (BOARD_HEIGHT < 16 || moveList[moveNum][0] <= 'Z')) { // drop move + snprintf(buf, MSG_SIZ, "%c@%c%d%s", moveList[moveNum][0], + moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4); + } else + snprintf(buf, MSG_SIZ, "%c%d%c%d%s", moveList[moveNum][0], moveList[moveNum][1] - '0', + moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4); + SendToProgram(buf, cps); } else SendToProgram(moveList[moveNum], cps); /* End of additions by Tord */ @@ -5746,6 +5764,14 @@ InitPosition(redraw) case VariantTwoKings: pieces = twoKingsArray; break; + case VariantGrand: + pieces = GrandArray; + nrCastlingRights = 0; + SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); + gameInfo.boardWidth = 10; + gameInfo.boardHeight = 10; + gameInfo.holdingsSize = 7; + break; case VariantCapaRandom: shuffleOpenings = TRUE; case VariantCapablanca: @@ -5862,7 +5888,7 @@ InitPosition(redraw) pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */ if(pawnRow < 1) pawnRow = 1; - if(gameInfo.variant == VariantMakruk) pawnRow = 2; + if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) pawnRow = 2; /* User pieceToChar list overrules defaults */ if(appData.pieceToCharTable != NULL) @@ -5876,7 +5902,7 @@ InitPosition(redraw) initialPosition[i][j] = s; if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue; - initialPosition[0][j] = pieces[0][j-gameInfo.holdingsWidth]; + initialPosition[gameInfo.variant == VariantGrand][j] = pieces[0][j-gameInfo.holdingsWidth]; initialPosition[pawnRow][j] = WhitePawn; initialPosition[BOARD_HEIGHT-pawnRow-1][j] = gameInfo.variant == VariantSpartan ? BlackLance : BlackPawn; if(gameInfo.variant == VariantXiangqi) { @@ -5889,7 +5915,13 @@ InitPosition(redraw) } } } - initialPosition[BOARD_HEIGHT-1][j] = pieces[1][j-gameInfo.holdingsWidth]; + if(gameInfo.variant == VariantGrand) { + if(j==BOARD_LEFT || j>=BOARD_RGHT-1) { + initialPosition[0][j] = WhiteRook; + initialPosition[BOARD_HEIGHT-1][j] = BlackRook; + } + } + initialPosition[BOARD_HEIGHT-1-(gameInfo.variant == VariantGrand)][j] = pieces[1][j-gameInfo.holdingsWidth]; } if( (gameInfo.variant == VariantShogi) && !overrule ) { @@ -6048,7 +6080,7 @@ DefaultPromoChoice(int white) static int autoQueen; // [HGM] oneclick int -HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) +HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice, int sweepSelect) { /* [HGM] rewritten IsPromotion to only flag promotions that offer a choice */ /* [HGM] add Shogi promotions */ @@ -6068,7 +6100,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) if(gameInfo.variant == VariantShogi) { promotionZoneSize = BOARD_HEIGHT/3; highestPromotingPiece = (int)WhiteFerz; - } else if(gameInfo.variant == VariantMakruk) { + } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) { promotionZoneSize = 3; } @@ -6130,9 +6162,9 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) } // give caller the default choice even if we will not make it *promoChoice = ToLower(PieceToChar(defaultPromoChoice)); - if(gameInfo.variant == VariantShogi) *promoChoice = '+'; - if(appData.sweepSelect && gameInfo.variant != VariantGreat - && gameInfo.variant != VariantShogi + if(gameInfo.variant == VariantShogi) *promoChoice = (defaultPromoChoice == piece ? '=' : '+'); + if( sweepSelect && gameInfo.variant != VariantGreat + && gameInfo.variant != VariantGrand && gameInfo.variant != VariantSuper) return FALSE; if(autoQueen) return FALSE; // predetermined @@ -6272,7 +6304,7 @@ OKToStartUserMove(x, y) Boolean OnlyMove(int *x, int *y, Boolean captures) { DisambiguateClosure cl; - if (appData.zippyPlay) return FALSE; + if (appData.zippyPlay || !appData.testLegality) return FALSE; switch(gameMode) { case MachinePlaysBlack: case IcsPlayingWhite: @@ -6514,8 +6546,8 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar) { char *bookHit = 0; - if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { - // [HGM] superchess: suppress promotions to non-available piece + if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) && promoChar != NULLCHAR) { + // [HGM] superchess: suppress promotions to non-available piece (but P always allowed) int k = PieceToNumber(CharToPiece(ToUpper(promoChar))); if(WhiteOnMove(currentMove)) { if(!boards[currentMove][k][BOARD_WIDTH-2]) return 0; @@ -6718,7 +6750,7 @@ MarkTargetSquares(int clear) for(x=0; x1) capt++; if(capt) @@ -6773,7 +6805,6 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } if (clickType == Press) ErrorPopDown(); - MarkTargetSquares(1); x = EventToSquare(xPix, BOARD_WIDTH); y = EventToSquare(yPix, BOARD_HEIGHT); @@ -6788,7 +6819,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) defaultPromoChoice = promoSweep; promoSweep = EmptySquare; // terminate sweep promoDefaultAltered = TRUE; - if(!selectFlag) x = fromX, y = fromY; // and fake up-click on same square if we were still selecting + if(!selectFlag && (x != toX || y != toY)) x = fromX, y = fromY; // and fake up-click on same square if we were still selecting } if(promotionChoice) { // we are waiting for a click to indicate promotion piece @@ -6797,13 +6828,14 @@ void LeftClick(ClickType clickType, int xPix, int yPix) if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y); if(gameInfo.holdingsWidth && (WhiteOnMove(currentMove) - ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0 - : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) { + ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y >= 0 + : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT) ) { // click in right holdings, for determining promotion piece ChessSquare p = boards[currentMove][y][x]; if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p); - if(p != EmptySquare) { - FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p))); + if(p == WhitePawn || p == BlackPawn) p = EmptySquare; // [HGM] Pawns could be valid as deferral + if(p != EmptySquare || gameInfo.variant == VariantGrand && toY != 0 && toY != BOARD_HEIGHT-1) { // [HGM] grand: empty square means defer + FinishMove(NormalMove, fromX, fromY, toX, toY, p==EmptySquare ? NULLCHAR : ToLower(PieceToChar(p))); fromX = fromY = -1; return; } @@ -6840,7 +6872,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) } return; } - fromX = x; fromY = y; + fromX = x; fromY = y; toX = toY = -1; if(!appData.oneClick || !OnlyMove(&x, &y, FALSE) || // even if only move, we treat as normal when this would trigger a promotion popup, to allow sweep selection appData.sweepSelect && CanPromote(boards[currentMove][fromY][fromX], fromY) && originalY != y) { @@ -6848,7 +6880,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) if (OKToStartUserMove(fromX, fromY)) { second = 0; MarkTargetSquares(0); - DragPieceBegin(xPix, yPix); dragging = 1; + DragPieceBegin(xPix, yPix, FALSE); dragging = 1; if(appData.sweepSelect && CanPromote(piece = boards[currentMove][fromY][fromX], fromY)) { promoSweep = defaultPromoChoice; selectFlag = 0; lastX = xPix; lastY = yPix; @@ -6887,6 +6919,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) /* Clicked again on same color piece -- changed his mind */ second = (x == fromX && y == fromY); promoDefaultAltered = FALSE; + MarkTargetSquares(1); if(!second || appData.oneClick && !OnlyMove(&x, &y, TRUE)) { if (appData.highlightDragging) { SetHighlights(x, y, -1, -1); @@ -6902,7 +6935,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix) fromX = x; fromY = y; dragging = 1; MarkTargetSquares(0); - DragPieceBegin(xPix, yPix); + DragPieceBegin(xPix, yPix, FALSE); if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) { promoSweep = defaultPromoChoice; selectFlag = 0; lastX = xPix; lastY = yPix; @@ -6953,13 +6986,25 @@ void LeftClick(ClickType clickType, int xPix, int yPix) toX = x; toY = y; saveAnimate = appData.animate; + MarkTargetSquares(1); if (clickType == Press) { if(gameMode == EditPosition && boards[currentMove][fromY][fromX] == EmptySquare) { // must be Edit Position mode with empty-square selected - fromX = x; fromY = y; DragPieceBegin(xPix, yPix); dragging = 1; // consider this a new attempt to drag + fromX = x; fromY = y; DragPieceBegin(xPix, yPix, FALSE); dragging = 1; // consider this a new attempt to drag if(x >= BOARD_LEFT && x < BOARD_RGHT) clearFlag = 1; // and defer click-click move of empty-square to up-click return; } + if(appData.sweepSelect && HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) { + ChessSquare piece = boards[currentMove][fromY][fromX]; + DragPieceBegin(xPix, yPix, TRUE); dragging = 1; + promoSweep = defaultPromoChoice; + if(PieceToChar(PROMOTED piece) == '+') promoSweep = PROMOTED piece; + selectFlag = 0; lastX = xPix; lastY = yPix; + Sweep(0); // Pawn that is going to promote: preview promotion piece + DisplayMessage("", _("Pull pawn backwards to under-promote")); + DrawPosition(FALSE, boards[currentMove]); + return; + } /* Finish clickclick move */ if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); @@ -7010,9 +7055,9 @@ void LeftClick(ClickType clickType, int xPix, int yPix) if(gatingPiece != EmptySquare) promoChoice = ToLower(PieceToChar(gatingPiece)); - if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice)) { + if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) { SetHighlights(fromX, fromY, toX, toY); - if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) { // [HGM] super: promotion to captured piece selected from holdings ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX]; promotionChoice = TRUE; @@ -8951,7 +8996,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) Board board; { ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0; - int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1; + int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand ? 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 */ @@ -9049,18 +9094,15 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[fromY][BOARD_LEFT] = EmptySquare; } else if ((board[fromY][fromX] == WhitePawn && gameInfo.variant != VariantXiangqi || board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi) - && toY >= BOARD_HEIGHT-promoRank + && toY >= BOARD_HEIGHT-promoRank && promoChar // defaulting to Q is done elsewhere ) { /* white pawn promotion */ board[toY][toX] = CharToPiece(ToUpper(promoChar)); - if (board[toY][toX] == EmptySquare) { - board[toY][toX] = WhiteQueen; - } if(gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */ board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); board[fromY][fromX] = EmptySquare; - } else if ((fromY == BOARD_HEIGHT-4) + } else if ((fromY >= BOARD_HEIGHT>>1) && (toX != fromX) && gameInfo.variant != VariantXiangqi && gameInfo.variant != VariantBerolina @@ -9113,18 +9155,15 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[toY][2] = BlackRook; } else if ((board[fromY][fromX] == BlackPawn && gameInfo.variant != VariantXiangqi || board[fromY][fromX] == BlackLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi) - && toY < promoRank + && toY < promoRank && promoChar ) { /* black pawn promotion */ 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 */ board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]); board[fromY][fromX] = EmptySquare; - } else if ((fromY == 3) + } else if ((fromY < BOARD_HEIGHT>>1) && (toX != fromX) && gameInfo.variant != VariantXiangqi && gameInfo.variant != VariantBerolina @@ -9185,7 +9224,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) if (captured != EmptySquare && gameInfo.holdingsSize > 0 && gameInfo.variant != VariantBughouse && gameInfo.variant != VariantSChess ) { /* [HGM] holdings: Add to holdings, if holdings exist */ - if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) { // [HGM] superchess: suppress flipping color of captured pieces by reverse pre-flip captured = (int) captured >= (int) BlackPawn ? BLACK_TO_WHITE captured : WHITE_TO_BLACK captured; } @@ -9236,8 +9275,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar board[toY][toX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); } - if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) - && promoChar != NULLCHAR && gameInfo.holdingsSize) { + if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) + && promoChar != NULLCHAR && gameInfo.holdingsSize) { // [HGM] superchess: take promotion piece out of holdings int k = PieceToNumber(CharToPiece(ToUpper(promoChar))); if((int)piece < (int)BlackPawn) { // determine stm from piece color @@ -9465,6 +9504,8 @@ InitChessProgram(cps, setup) overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8; if( gameInfo.variant == VariantSChess ) overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 7; + if( gameInfo.variant == VariantGrand ) + overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 10 || gameInfo.holdingsSize != 7; if(overruled) { snprintf(b, MSG_SIZ, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight, @@ -9654,7 +9695,7 @@ WriteTourneyFile(char *results) fprintf(f, "-loadPositionIndex %d\n", appData.loadPositionIndex); fprintf(f, "-rewindIndex %d\n", appData.rewindIndex); if(searchTime > 0) - fprintf(f, "-searchTime \"%s\"\n", appData.searchTime); + fprintf(f, "-searchTime \"%d:%02d\"\n", searchTime/60, searchTime%60); else { fprintf(f, "-mps %d\n", appData.movesPerSession); fprintf(f, "-tc %s\n", appData.timeControl); @@ -10018,7 +10059,7 @@ GameEnds(result, resultDetails, whosays) // now verify win claims, but not in drop games, as we don't understand those yet if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper - || gameInfo.variant == VariantGreat) && + || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) && (result == WhiteWins && claimer == 'w' || result == BlackWins && claimer == 'b' ) ) { // case to verify: engine claims own win if (appData.debugMode) { @@ -10044,7 +10085,8 @@ GameEnds(result, resultDetails, whosays) /* (Claiming a loss is accepted no questions asked!) */ } /* [HGM] bare: don't allow bare King to win */ - if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) + if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper + || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway && gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course... && result != GameIsDrawn) @@ -15169,8 +15211,6 @@ DisplayComment(moveNumber, text) char *text; { char title[MSG_SIZ]; - char buf[8000]; // comment can be long! - int score, depth; if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) { safeStrCpy(title, "Comment", sizeof(title)/sizeof(title[0])); @@ -15179,14 +15219,6 @@ DisplayComment(moveNumber, text) WhiteOnMove(moveNumber) ? " " : ".. ", parseList[moveNumber]); } - // [HGM] PV info: display PV info together with (or as) comment - if(moveNumber >= 0 && (depth = pvInfoList[moveNumber].depth) > 0) { - if(text == NULL) text = ""; - score = pvInfoList[moveNumber].score; - snprintf(buf,sizeof(buf)/sizeof(buf[0]), "%s%.2f/%d %d\n%s", score>0 ? "+" : "", score/100., - depth, (pvInfoList[moveNumber].time+50)/100, text); - text = buf; - } if (text != NULL && (appData.autoDisplayComment || commentUp)) CommentPopUp(title, text); } @@ -15791,7 +15823,7 @@ PositionToFEN(move, overrideCastling) { int i, j, fromX, fromY, toX, toY; int whiteToPlay; - char buf[128]; + char buf[MSG_SIZ]; char *p, *q; int emptycount; ChessSquare piece; @@ -15802,6 +15834,7 @@ PositionToFEN(move, overrideCastling) /* Piece placement data */ for (i = BOARD_HEIGHT - 1; i >= 0; i--) { + if(MSG_SIZ - (p - buf) < BOARD_RGHT - BOARD_LEFT + 20) { *p = 0; return StrSave(buf); } emptycount = 0; for (j = BOARD_LEFT; j < BOARD_RGHT; j++) { if (boards[move][i][j] == EmptySquare) {