X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=80356736968233e024367a769c6df8d6a32db610;hb=efc16c67bb82730127e429d77d2f670923e827c9;hp=a9b94ad996ca65550ec82c615176d7fc9b0781b6;hpb=db6fe5fa1497f58db1c4db398a9b431a4a610ba9;p=xboard.git diff --git a/backend.c b/backend.c index a9b94ad..8035673 100644 --- a/backend.c +++ b/backend.c @@ -618,6 +618,13 @@ ChessSquare GrandArray[2][BOARD_FILES] = { BlackMarshall, BlackAngel, BlackBishop, BlackKnight, EmptySquare } }; +ChessSquare ChuChessArray[2][BOARD_FILES] = { + { WhiteMan, WhiteKnight, WhiteBishop, WhiteCardinal, WhiteLion, + WhiteQueen, WhiteDragon, WhiteBishop, WhiteKnight, WhiteMan }, + { BlackMan, BlackKnight, BlackBishop, BlackDragon, BlackQueen, + BlackLion, BlackCardinal, BlackBishop, BlackKnight, BlackMan } +}; + #ifdef GOTHIC ChessSquare GothicArray[2][BOARD_FILES] = { { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall, @@ -1204,6 +1211,7 @@ InitBackEnd1 () case VariantGrand: /* should work */ case VariantSpartan: /* should work */ case VariantLion: /* should work */ + case VariantChuChess: /* should work */ break; } } @@ -2068,7 +2076,8 @@ StringToVariant (char *e) found = TRUE; } else for (i=0; i= VariantShogi && isalpha(p[strlen(variantNames[i])])) continue; v = (VariantClass) i; found = TRUE; break; @@ -5017,7 +5026,7 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps) char buf[MSG_SIZ]; if(moveList[moveNum][1] == '@' && moveList[moveNum][0] == '@') { - if(gameInfo.variant == VariantLion || gameInfo.variant == VariantChu) { + if(gameInfo.variant == VariantLion || gameInfo.variant == VariantChuChess || gameInfo.variant == VariantChu) { sprintf(buf, "%s@@@@\n", cps->useUsermove ? "usermove " : ""); SendToProgram(buf, cps); return; @@ -5289,25 +5298,39 @@ static int lastX, lastY, lastLeftX, lastLeftY, selectFlag; int dragging; static ClickType lastClickType; +int +Partner (ChessSquare *p) +{ // change piece into promotion partner if one shogi-promotes to the other + int stride = gameInfo.variant == VariantChu ? 22 : 11; + ChessSquare partner; + partner = (*p/stride & 1 ? *p - stride : *p + stride); + if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0; + *p = partner; + return 1; +} + void Sweep (int step) { ChessSquare king = WhiteKing, pawn = WhitePawn, last = promoSweep; + static int toggleFlag; if(gameInfo.variant == VariantKnightmate) king = WhiteUnicorn; if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway) king = EmptySquare; if(promoSweep >= BlackPawn) king = WHITE_TO_BLACK king, pawn = WHITE_TO_BLACK pawn; if(gameInfo.variant == VariantSpartan && pawn == BlackPawn) pawn = BlackLance, king = EmptySquare; - if(fromY != BOARD_HEIGHT-2 && fromY != 1) pawn = EmptySquare; + if(fromY != BOARD_HEIGHT-2 && fromY != 1 && gameInfo.variant != VariantChuChess) pawn = EmptySquare; + if(!step) toggleFlag = Partner(&last); // piece has shogi-promotion do { - promoSweep -= step; + if(step && !(toggleFlag && Partner(&promoSweep))) promoSweep -= step; if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap else if((int)promoSweep == -1) promoSweep = WhiteKing; else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn; else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing; if(!step) step = -1; } while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn || - appData.testLegality && (promoSweep == king || promoSweep == WhiteLion || promoSweep == BlackLion) || - IS_SHOGI(gameInfo.variant) && promoSweep != CHUPROMOTED last && last != CHUPROMOTED promoSweep && last != promoSweep); + !toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other + appData.testLegality && (promoSweep == king || gameInfo.variant != VariantChuChess && + (promoSweep == WhiteLion || promoSweep == BlackLion))); if(toX >= 0) { int victim = boards[currentMove][toY][toX]; boards[currentMove][toY][toX] = promoSweep; @@ -6054,6 +6077,12 @@ InitPosition (int redraw) pieces = lionArray; SetCharTable(pieceToChar, "PNBRQ................LKpnbrq................lk"); break; + case VariantChuChess: + pieces = ChuChessArray; + gameInfo.boardWidth = 10; + gameInfo.boardHeight = 10; + SetCharTable(pieceToChar, "PNBRQ.....M.+++......LKpnbrq.....m.+++......lk"); + break; case VariantFairy: pieces = fairyArray; SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk"); @@ -6108,7 +6137,8 @@ InitPosition (int redraw) pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */ if(pawnRow < 1) pawnRow = 1; - if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN || gameInfo.variant == VariantGrand) pawnRow = 2; + if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN || + gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) pawnRow = 2; if(gameInfo.variant == VariantChu) pawnRow = 3; /* User pieceToChar list overrules defaults */ @@ -6123,7 +6153,7 @@ InitPosition (int redraw) initialPosition[i][j] = s; if(j < BOARD_LEFT || j >= BOARD_RGHT || overrule) continue; - initialPosition[gameInfo.variant == VariantGrand][j] = pieces[0][j-gameInfo.holdingsWidth]; + initialPosition[gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess][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) { @@ -6145,14 +6175,15 @@ InitPosition (int redraw) initialPosition[BOARD_HEIGHT-1-i][j] = pieces[2*i+1][j-gameInfo.holdingsWidth]; } } - if(gameInfo.variant == VariantGrand) { + if(gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) { 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]; + initialPosition[BOARD_HEIGHT-1-(gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess)][j] = pieces[1][j-gameInfo.holdingsWidth]; } + if(gameInfo.variant == VariantChuChess) initialPosition[0][BOARD_WIDTH/2] = WhiteKing, initialPosition[BOARD_HEIGHT-1][BOARD_WIDTH/2-1] = BlackKing; if( (gameInfo.variant == VariantShogi) && !overrule ) { j=BOARD_LEFT+1; @@ -6430,7 +6461,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i /* [HGM] rewritten IsPromotion to only flag promotions that offer a choice */ /* [HGM] add Shogi promotions */ int promotionZoneSize=1, highestPromotingPiece = (int)WhitePawn; - ChessSquare piece; + ChessSquare piece, partner; ChessMove moveType; Boolean premove; @@ -6446,10 +6477,10 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece; promotionZoneSize = BOARD_HEIGHT/3; highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteLion; - } else if(gameInfo.variant == VariantShogi) { + } else if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantChuChess) { promotionZoneSize = BOARD_HEIGHT/3; highestPromotingPiece = (int)WhiteAlfil; - } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand) { + } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) { promotionZoneSize = 3; } @@ -6463,10 +6494,13 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i if((int)piece >= BlackPawn) { if(toY >= promotionZoneSize && fromY >= promotionZoneSize) return FALSE; + if(fromY < promotionZoneSize && gameInfo.variant == VariantChuChess) return FALSE; highestPromotingPiece = WHITE_TO_BLACK highestPromotingPiece; } else { if( toY < BOARD_HEIGHT - promotionZoneSize && fromY < BOARD_HEIGHT - promotionZoneSize) return FALSE; + if(fromY >= BOARD_HEIGHT - promotionZoneSize && gameInfo.variant == VariantChuChess) + return FALSE; } if( (int)piece > highestPromotingPiece ) return FALSE; // non-promoting piece @@ -6512,7 +6546,9 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i } // give caller the default choice even if we will not make it *promoChoice = ToLower(PieceToChar(defaultPromoChoice)); - if(IS_SHOGI(gameInfo.variant)) *promoChoice = (defaultPromoChoice == piece ? '=' : '+'); + partner = piece; // pieces can promote if the pieceToCharTable says so + if(IS_SHOGI(gameInfo.variant)) *promoChoice = (defaultPromoChoice == piece && sweepSelect ? '=' : '+'); // obsolete? + else if(Partner(&partner)) *promoChoice = (defaultPromoChoice == piece && sweepSelect ? NULLCHAR : '+'); if( sweepSelect && gameInfo.variant != VariantGreat && gameInfo.variant != VariantGrand && gameInfo.variant != VariantSuper) return FALSE; @@ -6523,7 +6559,8 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i gameMode == IcsPlayingBlack && WhiteOnMove(currentMove); if(appData.testLegality && !premove) { moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), - fromY, fromX, toY, toX, IS_SHOGI(gameInfo.variant) ? '+' : NULLCHAR); + fromY, fromX, toY, toX, IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantChuChess ? '+' : NULLCHAR); + if(moveType == IllegalMove) *promoChoice = NULLCHAR; // could be the fact we promoted was illegal if(moveType != WhitePromotion && moveType != BlackPromotion) return FALSE; } @@ -7178,14 +7215,15 @@ ChessSquare gatingPiece = EmptySquare; // exported to front-end, for dragging int CanPromote (ChessSquare piece, int y) { + int zone = (gameInfo.variant == VariantChuChess ? 3 : 1); if(gameMode == EditPosition) return FALSE; // no promotions when editing position // some variants have fixed promotion piece, no promotion at all, or another selection mechanism if(IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantXiangqi || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) return FALSE; - return (piece == BlackPawn && y == 1 || - piece == WhitePawn && y == BOARD_HEIGHT-2 || + return (piece == BlackPawn && y <= zone || + piece == WhitePawn && y >= BOARD_HEIGHT-1-zone || piece == BlackLance && y == 1 || piece == WhiteLance && y == BOARD_HEIGHT-2 ); } @@ -7456,8 +7494,11 @@ LeftClick (ClickType clickType, int xPix, int yPix) toY = y; } + piece = boards[currentMove][fromY][fromX]; + saveAnimate = appData.animate; if (clickType == Press) { + if(gameInfo.variant == VariantChuChess && piece != WhitePawn && piece != BlackPawn) defaultPromoChoice = piece; if(gameMode == EditPosition && boards[currentMove][fromY][fromX] == EmptySquare) { // must be Edit Position mode with empty-square selected fromX = x; fromY = y; DragPieceBegin(xPix, yPix, FALSE); dragging = 1; // consider this a new attempt to drag @@ -7473,9 +7514,8 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(marker[y][x] == 5) return; // [HGM] lion: to-click on cyan square; defer action to release if(legal[y][x] == 2 || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, FALSE)) { if(appData.sweepSelect) { - ChessSquare piece = boards[currentMove][fromY][fromX]; promoSweep = defaultPromoChoice; - if(PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece; + if(gameInfo.variant != VariantChuChess && PieceToChar(CHUPROMOTED piece) == '+') promoSweep = CHUPROMOTED piece; selectFlag = 0; lastX = xPix; lastY = yPix; Sweep(0); // Pawn that is going to promote: preview promotion piece sweepSelecting = 1; @@ -7491,7 +7531,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) ClearHighlights(); } } else if(sweepSelecting) { // this must be the up-click corresponding to the down-click that started the sweep - sweepSelecting = 0; + sweepSelecting = 0; appData.animate = FALSE; // do not animate, a selected piece already on to-square if (appData.animate || appData.highlightLastMove) { SetHighlights(fromX, fromY, toX, toY); } else { @@ -7507,6 +7547,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) ClearHighlights(); } #endif + 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 MarkTargetSquares(1); @@ -7573,7 +7614,7 @@ LeftClick (ClickType clickType, int xPix, int yPix) DisplayMessage("Click in holdings to choose piece", ""); return; } - PromotionPopUp(); + PromotionPopUp(promoChoice); } else { int oldMove = currentMove; UserMoveEvent(fromX, fromY, toX, toY, promoChoice); @@ -9659,7 +9700,7 @@ void ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) { ChessSquare captured = board[toY][toX], piece, king; int p, oldEP = EP_NONE, berolina = 0; - int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand ? 3 : 1; + int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 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 */ @@ -9959,6 +10000,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite ordinary Pawn promotion) */ board[toY][toX] = (ChessSquare) (CHUPROMOTED piece); + if(gameInfo.variant == VariantChuChess && (piece == WhiteKnight || piece == BlackKnight)) + board[toY][toX] = piece + WhiteLion - WhiteKnight; // adjust Knight promotions to Lion } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar ChessSquare newPiece = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar)); if((newPiece <= WhiteMan || newPiece >= BlackPawn && newPiece <= BlackMan) // unpromoted piece specified @@ -10174,6 +10217,7 @@ NonStandardBoardSize (VariantClass v, int boardWidth, int boardHeight, int holdi if( v == VariantGreat ) width = 10, holdings = 8; if( v == VariantSChess ) holdings = 7; if( v == VariantGrand ) width = 10, height = 10, holdings = 7; + if( v == VariantChuChess) width = 10, height = 10; if( v == VariantChu ) width = 12, height = 12; return boardWidth >= 0 && boardWidth != width || // -1 is default, boardHeight >= 0 && boardHeight != height || // and thus by definition OK