X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=backend.c;h=933b07a169a8286737bd5dae8b09e6f6dafc7641;hb=ab773ff40f992d0462d500b429d4df863be9d288;hp=37929713badf534efd4f20f21392efc44d98aaeb;hpb=d1638304f504ca6cbfa36eb7a951b530f374bd10;p=xboard.git diff --git a/backend.c b/backend.c index 3792971..933b07a 100644 --- a/backend.c +++ b/backend.c @@ -261,7 +261,7 @@ void ics_update_width P((int new_width)); extern char installDir[MSG_SIZ]; VariantClass startVariant; /* [HGM] nicks: initial variant */ Boolean abortMatch; -int deadRanks; +int deadRanks, handSize; extern int tinyLayout, smallLayout; ChessProgramStats programStats; @@ -2485,7 +2485,7 @@ CopyHoldings (Board board, char *holdings, ChessSquare lowestPiece) if( (int)lowestPiece >= BlackPawn ) { holdingsColumn = 0; countsColumn = 1; - holdingsStartRow = BOARD_HEIGHT-1; + holdingsStartRow = handSize-1; direction = -1; } else { holdingsColumn = BOARD_WIDTH-1; @@ -2494,7 +2494,7 @@ CopyHoldings (Board board, char *holdings, ChessSquare lowestPiece) direction = 1; } - for(i=0; i= j); seed /= 3; p = board[0][BOARD_LEFT+j]; board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p); board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++; - board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++; + board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++; j = seed%3; seed /= 3; p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p); board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++; - board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++; + board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++; j = seed%2 + (seed%2 >= j); seed /= 2; p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p); board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++; - board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++; + board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++; j = seed%4; seed /= 4; put(board, exoPieces[3], 0, j, ANY); j = seed%3; seed /= 3; put(board, exoPieces[2], 0, j, ANY); j = seed%2; seed /= 2; put(board, exoPieces[1], 0, j, ANY); @@ -6363,6 +6366,7 @@ InitPosition (int redraw) if(BOARD_HEIGHT > BOARD_RANKS || BOARD_WIDTH > BOARD_FILES) DisplayFatalError(_("Recompile to support this BOARD_RANKS or BOARD_FILES!"), 0, 2); + handSize = BOARD_HEIGHT; pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */ if(pawnRow < 1) pawnRow = 1; if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN || @@ -6440,8 +6444,8 @@ InitPosition (int redraw) if(gameInfo.variant == VariantGreat) { // promotion commoners initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-1] = WhiteMan; initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-2] = 9; - initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan; - initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9; + initialPosition[handSize-1-PieceToNumber(WhiteMan)][0] = BlackMan; + initialPosition[handSize-1-PieceToNumber(WhiteMan)][1] = 9; } if( gameInfo.variant == VariantSChess ) { initialPosition[1][0] = BlackMarshall; @@ -6451,6 +6455,7 @@ InitPosition (int redraw) initialPosition[1][1] = initialPosition[2][1] = initialPosition[6][BOARD_WIDTH-2] = initialPosition[5][BOARD_WIDTH-2] = 1; } + initialPosition[CHECK_COUNT] = (gameInfo.variant == Variant3Check ? 0x303 : 0); if (appData.debugMode) { fprintf(debugFP, "shuffleOpenings = %d\n", shuffleOpenings); } @@ -6707,12 +6712,13 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i piece = boards[currentMove][fromY][fromX]; if(gameInfo.variant == VariantChu) { - promotionZoneSize = BOARD_HEIGHT/3; + promotionZoneSize = (BOARD_HEIGHT - deadRanks)/3; if(legal[toY][toX] == 6) return FALSE; // no promotion if highlights deny it highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing; } else if(gameInfo.variant == VariantShogi) { - promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8); + promotionZoneSize = (BOARD_HEIGHT- deadRanks)/3 +(BOARD_HEIGHT == 8); highestPromotingPiece = (int)WhiteAlfil; + if(PieceToChar(piece) != '+' || PieceToChar(CHUPROMOTED(piece)) == '+') highestPromotingPiece = piece; } else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) { promotionZoneSize = 3; } @@ -6730,9 +6736,9 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i 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) + if( toY < BOARD_HEIGHT - deadRanks - promotionZoneSize && + fromY < BOARD_HEIGHT - deadRanks - promotionZoneSize) return FALSE; + if(fromY >= BOARD_HEIGHT - deadRanks - promotionZoneSize && gameInfo.variant == VariantChuChess) return FALSE; } @@ -6748,9 +6754,9 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i return FALSE; } } else { - if(toY == BOARD_HEIGHT-1 && piece == WhitePawn || - toY == BOARD_HEIGHT-1 && piece == WhiteQueen || - toY >= BOARD_HEIGHT-2 && piece == WhiteKnight) { + if(toY == BOARD_HEIGHT-deadRanks-1 && piece == WhitePawn || + toY == BOARD_HEIGHT-deadRanks-1 && piece == WhiteQueen || + toY >= BOARD_HEIGHT-deadRanks-2 && piece == WhiteKnight) { *promoChoice = '+'; return FALSE; } @@ -7156,7 +7162,7 @@ UserMoveEvent (int fromX, int fromY, int toX, int toY, int promoChar) if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]); // 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 + if(fromX == 0) fromY = handSize-1 - fromY; // black holdings upside-down fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings while(PieceToChar(fromX) == '.' || PieceToChar(fromX) == '+' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; fromY = DROP_RANK; @@ -7213,7 +7219,7 @@ FinishMove (ChessMove moveType, int fromX, int fromY, int toX, int toY, int prom if(WhiteOnMove(currentMove)) { if(!boards[currentMove][k][BOARD_WIDTH-2]) return 0; } else { - if(!boards[currentMove][BOARD_HEIGHT-1-k][1]) return 0; + if(!boards[currentMove][handSize-1-k][1]) return 0; } } @@ -7462,7 +7468,7 @@ MarkTargetSquares (int clear) if(PosFlags(0) & F_MANDATORY_CAPTURE) { for(x=0; x1) capt++; if(capt) - for(x=0; x= BOARD_HEIGHT-1-zone || + piece == WhitePawn && y >= BOARD_HEIGHT-1-deadRanks-zone || piece == BlackLance && y <= zone || - piece == WhiteLance && y >= BOARD_HEIGHT-1-zone ); + piece == WhiteLance && y >= BOARD_HEIGHT-1-deadRanks-zone ); } void @@ -7880,8 +7886,8 @@ LeftClick (ClickType clickType, int xPix, int yPix) if(x == BOARD_LEFT-2 && piece >= BlackPawn) { n = PieceToNumber(piece - (int)BlackPawn); if(n >= gameInfo.holdingsSize) { n = 0; piece = BlackPawn; } - boards[currentMove][BOARD_HEIGHT-1 - n][0] = piece; - boards[currentMove][BOARD_HEIGHT-1 - n][1]++; + boards[currentMove][handSize-1 - n][0] = piece; + boards[currentMove][handSize-1 - n][1]++; } else if(x == BOARD_RGHT+1 && piece < BlackPawn) { n = PieceToNumber(piece); @@ -10030,7 +10036,7 @@ void ParseGameHistory (char *game) { ChessMove moveType; - int fromX, fromY, toX, toY, boardIndex; + int fromX, fromY, toX, toY, boardIndex, mask; char promoChar; char *p, *q; char buf[MSG_SIZ]; @@ -10191,15 +10197,18 @@ ParseGameHistory (char *game) strcat(moveList[boardIndex], "\n"); boardIndex++; ApplyMove(fromX, fromY, toX, toY, promoChar, boards[boardIndex]); + mask = (WhiteOnMove(boardIndex) ? 0xFF : 0xFF00); switch (MateTest(boards[boardIndex], PosFlags(boardIndex)) ) { case MT_NONE: case MT_STALEMATE: default: break; case MT_CHECK: - if(!IS_SHOGI(gameInfo.variant)) - strcat(parseList[boardIndex - 1], "+"); - break; + if(boards[boardIndex][CHECK_COUNT]) boards[boardIndex][CHECK_COUNT] -= mask & 0x101; + if(!boards[boardIndex][CHECK_COUNT] || boards[boardIndex][CHECK_COUNT] & mask) { + if(!IS_SHOGI(gameInfo.variant)) strcat(parseList[boardIndex - 1], "+"); + break; + } case MT_CHECKMATE: case MT_STAINMATE: strcat(parseList[boardIndex - 1], "#"); @@ -10220,9 +10229,9 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) /* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */ if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A; - oldEP = (signed char)board[EP_STATUS]; epRank = board[EP_RANK]; epFile = board[EP_FILE]; lastFile = board[LAST_FILE],lastRank = board[LAST_RANK]; + oldEP = (signed char)board[EP_STATUS]; epRank = board[EP_RANK]; epFile = board[EP_FILE]; lastFile = board[LAST_TO] & 255,lastRank = board[LAST_TO] >> 8; board[EP_STATUS] = EP_NONE; - board[EP_FILE] = board[EP_RANK] = board[LAST_FILE] = board[LAST_RANK] = 100; + board[EP_FILE] = board[EP_RANK] = 100, board[LAST_TO] = 0x4040; if (fromY == DROP_RANK) { /* must be first */ @@ -10278,7 +10287,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) if(toX fromX) board[EP_STATUS] = toX; - board[LAST_FILE] = toX; board[LAST_RANK] = toY; + board[LAST_TO] = toX + 256*toY; } } else if( pawn == BlackPawn ) { @@ -10292,7 +10301,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) if(toX fromX) board[EP_STATUS] = toX; - board[LAST_FILE] = toX; board[LAST_RANK] = toY; + board[LAST_TO] = toX + 256*toY; } } @@ -10505,10 +10514,10 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) p -= (int)BlackPawn; p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) p = 0; - if(--board[BOARD_HEIGHT-1-p][1] <= 0) - board[BOARD_HEIGHT-1-p][0] = EmptySquare; - if((int)board[BOARD_HEIGHT-1-p][1] < 0) - board[BOARD_HEIGHT-1-p][1] = 0; + if(--board[handSize-1-p][1] <= 0) + board[handSize-1-p][0] = EmptySquare; + if((int)board[handSize-1-p][1] < 0) + board[handSize-1-p][1] = 0; } } if (captured != EmptySquare && gameInfo.holdingsSize > 0 @@ -10538,8 +10547,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) } p = PieceToNumber((ChessSquare)p); if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; } - board[BOARD_HEIGHT-1-p][1]++; - board[BOARD_HEIGHT-1-p][0] = WHITE_TO_BLACK captured; + board[handSize-1-p][1]++; + board[handSize-1-p][0] = WHITE_TO_BLACK captured; } } } else if (gameInfo.variant == VariantAtomic) { @@ -10579,8 +10588,8 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) if(!--board[k][BOARD_WIDTH-2]) board[k][BOARD_WIDTH-1] = EmptySquare; } else { - if(!--board[BOARD_HEIGHT-1-k][1]) - board[BOARD_HEIGHT-1-k][0] = EmptySquare; + if(!--board[handSize-1-k][1]) + board[handSize-1-k][0] = EmptySquare; } } } @@ -10589,7 +10598,7 @@ ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board) void MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) { - int x = toX, y = toY; + int x = toX, y = toY, mask; char *s = parseList[forwardMostMove]; ChessSquare p = boards[forwardMostMove][toY][toX]; // forwardMostMove++; // [HGM] bare: moved downstream @@ -10685,15 +10694,18 @@ MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) } CoordsToComputerAlgebraic(fromY, fromX, toY, toX, promoChar, moveList[forwardMostMove - 1]); + mask = (WhiteOnMove(forwardMostMove) ? 0xFF : 0xFF00); switch (MateTest(boards[forwardMostMove], PosFlags(forwardMostMove)) ) { case MT_NONE: case MT_STALEMATE: default: break; case MT_CHECK: - if(!IS_SHOGI(gameInfo.variant)) - strcat(parseList[forwardMostMove - 1], "+"); - break; + if(boards[forwardMostMove][CHECK_COUNT]) boards[forwardMostMove][CHECK_COUNT] -= mask & 0x101; + if(!boards[forwardMostMove][CHECK_COUNT] || boards[forwardMostMove][CHECK_COUNT] & mask) { + if(!IS_SHOGI(gameInfo.variant)) strcat(parseList[forwardMostMove - 1], "+"); + break; + } case MT_CHECKMATE: case MT_STAINMATE: strcat(parseList[forwardMostMove - 1], "#"); @@ -15703,8 +15715,8 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y) if(x == BOARD_LEFT-2 && selection >= BlackPawn) { n = PieceToNumber(selection - BlackPawn); if(n >= gameInfo.holdingsSize) { n = 0; selection = BlackPawn; } - boards[0][BOARD_HEIGHT-1-n][0] = selection; - boards[0][BOARD_HEIGHT-1-n][1]++; + boards[0][handSize-1-n][0] = selection; + boards[0][handSize-1-n][1]++; } else if(x == BOARD_RGHT+1 && selection < BlackPawn) { n = PieceToNumber(selection); @@ -18435,13 +18447,15 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) fromY = moveList[move - 1][1] - ONE; toX = moveList[move - 1][2] - AAA; toY = moveList[move - 1][3] - ONE; - if (fromY == (whiteToPlay ? BOARD_HEIGHT-2 : 1) && - toY == (whiteToPlay ? BOARD_HEIGHT-4 : 3) && - boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) && - fromX == toX) { + if ((whiteToPlay ? toY < fromY - 1 : toY > fromY + 1) && + boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) ) { /* 2-square pawn move just happened */ - *p++ = toX + AAA; - *p++ = whiteToPlay ? '6'+BOARD_HEIGHT-8 : '3'; + *p++ = (3*toX + 5*fromX + 4)/8 + AAA; + *p++ = (3*toY + 5*fromY + 4)/8 + ONE; + if(gameInfo.variant == VariantBerolina) { + *p++ = toX + AAA; + *p++ = toY + ONE; + } } else { *p++ = '-'; } @@ -18460,6 +18474,12 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts) } } + i = boards[move][CHECK_COUNT]; + if(i) { + sprintf(p, "%d+%d ", i&255, i>>8); + while(*p) p++; + } + if(moveCounts) { int i = 0, j=move; @@ -18597,8 +18617,8 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) i = (int)piece - (int)BlackPawn; i = PieceToNumber((ChessSquare)i); if( i >= gameInfo.holdingsSize ) return FALSE; - board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */ - board[BOARD_HEIGHT-1-i][1]++; /* black counts */ + board[handSize-1-i][0] = piece; /* black holdings */ + board[handSize-1-i][1]++; /* black counts */ bcnt++; } else { i = (int)piece - (int)WhitePawn; @@ -18812,18 +18832,38 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) if(*p=='-') { p++; board[EP_STATUS] = EP_NONE; } else { - char c = *p++ - AAA; - - if(c < BOARD_LEFT || c >= BOARD_RGHT) return TRUE; - if(*p >= '0' && *p <='9') p++; - board[EP_STATUS] = c; + int d, r, c = *p - AAA; + + if(c >= BOARD_LEFT && c < BOARD_RGHT) { + p++; + board[EP_STATUS] = board[EP_FILE] = c; r = 0; + if(*p >= '0' && *p <='9') r = board[EP_RANK] = *p++ - ONE; + d = (r < BOARD_HEIGHT << 1 ? 1 : -1); // assume double-push (P next to e.p. square nearer center) + if(board[r+d][c] == EmptySquare) d *= 2; // but if no Pawn there, triple push + board[LAST_TO] = 256*(r + d) + c; + c = *p++ - AAA; + if(c >= BOARD_LEFT && c < BOARD_RGHT) { // mover explicitly mentioned + if(*p >= '0' && *p <='9') r = board[EP_RANK] = *p++ - ONE; + board[LAST_TO] = 256*r + c; + if(!(board[EP_RANK]-r & 1)) board[EP_RANK] |= 128; + } + } } } + while(*p == ' ') p++; + + board[CHECK_COUNT] = 0; // [HGM] 3check: check-count field + if(sscanf(p, "%d+%d", &i, &j) == 2) { + board[CHECK_COUNT] = i + 256*j; + while(*p && *p != ' ') p++; + } - if(sscanf(p, "%d", &i) == 1) { + c = sscanf(p, "%d%*d +%d+%d", &i, &j, &k); + if(c > 0) { FENrulePlies = i; /* 50-move ply counter */ /* (The move number is still ignored) */ + if(c == 3 && !board[CHECK_COUNT]) board[CHECK_COUNT] = (3 - j) + 256*(3 - k); // SCIDB-style check count } return TRUE;