From 91f35c4c0e1494e9711f26bb86f843e176c81321 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Sun, 31 Oct 2010 13:16:01 +0100 Subject: [PATCH] Fix spurious promotions with legality testing off The recent promotion patch had broken playing without legality testing completely: without legality testing one always gets the piece that was asked for, but a NULLCHAR should not be taken as a request for a piece! But it was, and this resulted in any moved piece turning into a white Pawn! For true promotions the piece was always black, which was also not very useful. Also revert to the use of '+' as internal Shogi promoChar, because pre-processing turns out not to be possible when reading a game file. In stead parse any trailing '+' on moves as promoChar. Downside: '++' can no longer be recognized as checkmate symbol. --- backend.c | 25 ++++++++----------------- moves.c | 31 +++++++++++++++---------------- parser.l | 35 +++++++++++++++++++++-------------- winboard/winboard.c | 2 +- xboard.c | 2 +- 5 files changed, 46 insertions(+), 49 deletions(-) diff --git a/backend.c b/backend.c index 5c7ebad..25fe5f5 100644 --- a/backend.c +++ b/backend.c @@ -4804,7 +4804,7 @@ CoordsToComputerAlgebraic(rf, ff, rt, ft, promoChar, move) AAA + ff, ONE + rf, AAA + ft, ONE + rt); } else { sprintf(move, "%c%c%c%c%c\n", - AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar == '^' ? '+' : promoChar); + AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar); } } } @@ -4884,16 +4884,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar) int *fromX, *fromY, *toX, *toY; char *promoChar; { - char moveCopy[20], *p = moveCopy; - strncpy(moveCopy, move, 20); // make a copy of move to preprocess it - if(gameInfo.variant == VariantShogi) { - while(*p && *p != ' ') p++; - if(p[-1] == '+') p[-1] = '^'; // in Shogi '+' is promotion, distinguish from check - } - if (appData.debugMode) { - fprintf(debugFP, "move to parse: %s\n", moveCopy); - } - *moveType = yylexstr(moveNum, moveCopy, yy_textstr, sizeof yy_textstr); + *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr); switch (*moveType) { case WhitePromotion: @@ -5700,14 +5691,14 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) if(toY == 0 && piece == BlackPawn || toY == 0 && piece == BlackQueen || toY <= 1 && piece == BlackKnight) { - *promoChoice = '^'; + *promoChoice = '+'; return FALSE; } } else { if(toY == BOARD_HEIGHT-1 && piece == WhitePawn || toY == BOARD_HEIGHT-1 && piece == WhiteQueen || toY >= BOARD_HEIGHT-2 && piece == WhiteKnight) { - *promoChoice = '^'; + *promoChoice = '+'; return FALSE; } } @@ -5744,7 +5735,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice) gameMode == IcsPlayingBlack && WhiteOnMove(currentMove); if(appData.testLegality && !premove) { moveType = LegalityTest(boards[currentMove], PosFlags(currentMove), - fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '^' : NULLCHAR); + fromY, fromX, toY, toX, gameInfo.variant == VariantShogi ? '+' : NULLCHAR); if(moveType != WhitePromotion && moveType != BlackPromotion) return FALSE; } @@ -8650,11 +8641,11 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board) board[toY][toX] = EmptySquare; } } - if(promoChar == '^') { + if(promoChar == '+') { /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */ board[toY][toX] = (ChessSquare) (PROMOTED piece); - } else if(!appData.testLegality) { // without legality testing, unconditionally believe promoChar - board[toY][toX] = CharToPiece(promoChar); + } 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) { diff --git a/moves.c b/moves.c index a0f7b7e..89af9a0 100644 --- a/moves.c +++ b/moves.c @@ -1037,9 +1037,9 @@ ChessMove LegalityTest(board, flags, rf, ff, rt, ft, promoChar) if(promoChar == 'd' && (piece == WhiteRook || piece == BlackRook) || promoChar == 'h' && (piece == WhiteBishop || piece == BlackBishop) || promoChar == 'g' && (piece <= WhiteFerz || piece <= BlackFerz && piece >= BlackPawn) ) - promoChar = '^'; // allowed ICS notations + promoChar = '+'; // allowed ICS notations if(appData.debugMode)fprintf(debugFP,"SHOGI promoChar = %c\n", promoChar ? promoChar : '-'); - if(promoChar != NULLCHAR && promoChar != '^' && promoChar != '=') + if(promoChar != NULLCHAR && promoChar != '+' && promoChar != '=') return CharToPiece(promoChar) == EmptySquare ? ImpossibleMove : IllegalMove; else if(flags & F_WHITE_ON_MOVE) { if( (int) piece < (int) WhiteWazir && @@ -1048,16 +1048,16 @@ if(appData.debugMode)fprintf(debugFP,"SHOGI promoChar = %c\n", promoChar ? promo piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */ cl.kind = promoChar == '=' ? IllegalMove : WhitePromotion; else /* promotion optional, default is defer */ - cl.kind = promoChar == '^' ? WhitePromotion : WhiteNonPromotion; - } else cl.kind = promoChar == '^' ? IllegalMove : NormalMove; + cl.kind = promoChar == '+' ? WhitePromotion : WhiteNonPromotion; + } else cl.kind = promoChar == '+' ? IllegalMove : NormalMove; } else { if( (int) piece < (int) BlackWazir && (rf < BOARD_HEIGHT/3 || rt < BOARD_HEIGHT/3) ) { if( (piece == BlackPawn || piece == BlackQueen) && rt < 1 || piece == BlackKnight && rt < 2 ) /* promotion obligatory */ cl.kind = promoChar == '=' ? IllegalMove : BlackPromotion; else /* promotion optional, default is defer */ - cl.kind = promoChar == '^' ? BlackPromotion : BlackNonPromotion; - } else cl.kind = promoChar == '^' ? IllegalMove : NormalMove; + cl.kind = promoChar == '+' ? BlackPromotion : BlackNonPromotion; + } else cl.kind = promoChar == '+' ? IllegalMove : NormalMove; } } } else @@ -1228,14 +1228,14 @@ void Disambiguate(board, flags, closure) if (c == 'x') c = NULLCHAR; // get rid of any 'x' (which should never happen?) if(gameInfo.variant == VariantShogi) { - /* [HGM] Shogi promotions. On input, '=' means defer, '^' promote. Afterwards, c is set to '+' for promotions, NULL other */ + /* [HGM] Shogi promotions. On input, '=' means defer, '+' promote. Afterwards, c is set to '+' for promotions, NULL other */ if(closure->rfIn != DROP_RANK && closure->kind == NormalMove) { ChessSquare piece = closure->piece; if (c == 'd' && (piece == WhiteRook || piece == BlackRook) || c == 'h' && (piece == WhiteBishop || piece == BlackBishop) || c == 'g' && (piece <= WhiteFerz || piece <= BlackFerz && piece >= BlackPawn) ) - c = '^'; // allowed ICS notations - if(c != NULLCHAR && c != '^' && c != '=') closure->kind = IllegalMove; // otherwise specifying a piece is illegal + c = '+'; // allowed ICS notations + if(c != NULLCHAR && c != '+' && c != '=') closure->kind = IllegalMove; // otherwise specifying a piece is illegal else if(flags & F_WHITE_ON_MOVE) { if( (int) piece < (int) WhiteWazir && (closure->rf >= BOARD_HEIGHT-(BOARD_HEIGHT/3) || closure->rt >= BOARD_HEIGHT-(BOARD_HEIGHT/3)) ) { @@ -1243,19 +1243,19 @@ void Disambiguate(board, flags, closure) piece == WhiteKnight && closure->rt > BOARD_HEIGHT-3) /* promotion mandatory */ closure->kind = c == '=' ? IllegalMove : WhitePromotion; else /* promotion optional, default is defer */ - closure->kind = c == '^' ? WhitePromotion : WhiteNonPromotion; - } else closure->kind = c == '^' ? IllegalMove : NormalMove; + closure->kind = c == '+' ? WhitePromotion : WhiteNonPromotion; + } else closure->kind = c == '+' ? IllegalMove : NormalMove; } else { if( (int) piece < (int) BlackWazir && (closure->rf < BOARD_HEIGHT/3 || closure->rt < BOARD_HEIGHT/3) ) { if( (piece == BlackPawn || piece == BlackQueen) && closure->rt < 1 || piece == BlackKnight && closure->rt < 2 ) /* promotion obligatory */ closure->kind = c == '=' ? IllegalMove : BlackPromotion; else /* promotion optional, default is defer */ - closure->kind = c == '^' ? BlackPromotion : BlackNonPromotion; - } else closure->kind = c == '^' ? IllegalMove : NormalMove; + closure->kind = c == '+' ? BlackPromotion : BlackNonPromotion; + } else closure->kind = c == '+' ? IllegalMove : NormalMove; } } - if(closure->kind == WhitePromotion || closure->kind == BlackPromotion) c = '^'; else + if(closure->kind == WhitePromotion || closure->kind == BlackPromotion) c = '+'; else if(closure->kind == WhiteNonPromotion || closure->kind == BlackNonPromotion) c = '='; } else if (closure->kind == WhitePromotion || closure->kind == BlackPromotion) { @@ -1270,7 +1270,7 @@ void Disambiguate(board, flags, closure) } else if (c != NULLCHAR) closure->kind = IllegalMove; closure->promoChar = ToLower(c); // this can be NULLCHAR! Note we keep original promoChar even if illegal. - if(c != '^' && c != '=' && c != NULLCHAR && CharToPiece(c) == EmptySquare) + if(c != '+' && c != '=' && c != NULLCHAR && CharToPiece(c) == EmptySquare) closure->kind = ImpossibleMove; // but we cannot handle non-existing piece types! if (closure->count > 1) { closure->kind = AmbiguousMove; @@ -1501,7 +1501,6 @@ ChessMove CoordsToAlgebraic(board, flags, rf, ff, rt, ft, promoChar, out) else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; } if (gameInfo.variant == VariantShogi) { /* [HGM] in Shogi non-pawns can promote */ - if(promoChar == '^') promoChar = '+'; *outp++ = promoChar; // Don't bother to correct move type, return value is never used! } *outp = NULLCHAR; diff --git a/parser.l b/parser.l index 021047b..17d7915 100644 --- a/parser.l +++ b/parser.l @@ -66,7 +66,7 @@ * Ranks can be 0-9. The parser returns 0 for off-board files and ranks. * For an unknown piece (as mover or promotion piece) it returns * IllegalMove, like it does when the piece doesn't match. - * Promotions can now also be appended Shogi-style, a bare '=' or '^', + * Promotions can now also be appended Shogi-style, a bare '=' or '+', * and this is then returned as promotion character. The piece indicator * can be prefixed by a '+' to indicate it is a promoted piece. */ @@ -178,7 +178,7 @@ extern void CopyBoard P((Board to, Board from)); %} %% -"+"?[A-Z][/]?[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=^])? { +"+"?[A-Z][/]?[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=+])? { /* * Fully-qualified algebraic move, possibly with promotion */ @@ -215,6 +215,7 @@ extern void CopyBoard P((Board to, Board from)); } else { c = currentMoveString[4] = ToLower(yytext[yyleng-1]); } + if(c == '+' && gameInfo.variant != VariantShogi) c = currentMoveString[4] = NULLCHAR; // + means check outside Shogi currentMoveString[5] = NULLCHAR; } @@ -256,7 +257,7 @@ extern void CopyBoard P((Board to, Board from)); else if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); else if(gameInfo.variant == VariantShogi) - currentMoveString[4] = '^'; + currentMoveString[4] = '+'; else currentMoveString[4] = PieceToChar(BlackQueen); } else if(result == WhiteNonPromotion || result == BlackNonPromotion) @@ -267,7 +268,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) result; } -[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Za-z]\)?)|[=^])? { +[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Za-z]\)?)|[=+])? { /* * Simple algebraic move, possibly with promotion * [HGM] Engine moves are received in this format, with lower-case promoChar! @@ -293,6 +294,7 @@ extern void CopyBoard P((Board to, Board from)); } else { c = currentMoveString[4] = ToLower(yytext[yyleng-1]); } + if(c == '+' && gameInfo.variant != VariantShogi) c = currentMoveString[4] = NULLCHAR; // + means check outside Shogi currentMoveString[5] = NULLCHAR; } @@ -322,7 +324,7 @@ extern void CopyBoard P((Board to, Board from)); else if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); else if(gameInfo.variant == VariantShogi) - currentMoveString[4] = '^'; // Queen might not be defined in mini variants! + currentMoveString[4] = '+'; // Queen might not be defined in mini variants! else currentMoveString[4] = PieceToChar(BlackQueen); } else if(result == WhiteNonPromotion || result == BlackNonPromotion) @@ -377,7 +379,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) result; } -[a-l][0-9]((=?\(?[A-Za-z]\)?)|[=^])? { +[a-l][0-9]((=?\(?[A-Za-z]\)?)|[=+])? { /* * Pawn move, possibly with promotion */ @@ -395,7 +397,8 @@ extern void CopyBoard P((Board to, Board from)); cl.ffIn = yytext[0] - AAA; cl.rtIn = yytext[1] - ONE; cl.ftIn = yytext[0] - AAA; - c = cl.promoCharIn = ToLower(yytext[2+skip]); + cl.promoCharIn = ToLower(yytext[2+skip]); + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.rtIn >= BOARD_HEIGHT || @@ -446,7 +449,8 @@ extern void CopyBoard P((Board to, Board from)); cl.ffIn = yytext[0] - AAA; cl.rtIn = -1; cl.ftIn = yytext[1+skip1] - AAA; - c = cl.promoCharIn = yytext[2+skip1+skip2]; + cl.promoCharIn = yytext[2+skip1+skip2]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.ffIn >= BOARD_RGHT || @@ -467,7 +471,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) cl.kind; } -[a-l][xX:]?[a-l][0-9]((=?\(?[A-Z]\)?)|ep|"e.p."|[=^])? { +[a-l][xX:]?[a-l][0-9]((=?\(?[A-Z]\)?)|ep|"e.p."|[=+])? { /* * unambiguously abbreviated Pawn capture, possibly with promotion */ @@ -523,8 +527,9 @@ extern void CopyBoard P((Board to, Board from)); else c = currentMoveString[4] = ToLower(yytext[yyleng-1]); currentMoveString[5] = NULLCHAR; - if(c != '=' && c != '^' && CharToPiece(c) == EmptySquare) + if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare) return ImpossibleMove; + if(c == '+' && gameInfo.variant != VariantShogi) c = currentMoveString[4] = NULLCHAR; // + means check outside Shogi } else { currentMoveString[4] = NULLCHAR; } @@ -546,7 +551,7 @@ extern void CopyBoard P((Board to, Board from)); if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); if(gameInfo.variant == VariantShogi) - currentMoveString[4] = '^'; + currentMoveString[4] = '+'; } else if(result == WhiteNonPromotion || result == BlackNonPromotion) currentMoveString[4] = '='; currentMoveString[5] = NULLCHAR; @@ -585,7 +590,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) IllegalMove; } -"+"?[A-Z][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=^])? { +"+"?[A-Z][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=+])? { /* * piece move, possibly ambiguous */ @@ -613,8 +618,9 @@ extern void CopyBoard P((Board to, Board from)); cl.ftIn = yytext[1+skip] - AAA; cl.promoCharIn = NULLCHAR; - if(yyleng-skip > 3) /* [HGM] can have Shogi-style promotion */ + if(yyleng-skip > 3 && gameInfo.variant == VariantShogi) /* [HGM] can have Shogi-style promotion */ cl.promoCharIn = yytext[yyleng-1-(yytext[yyleng-1]==')')]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi if (appData.debugMode) { fprintf(debugFP, "Parser Qa1: yyleng=%d, %d(%d,%d)-(%d,%d) = %d (%c)\n", @@ -641,7 +647,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) cl.kind; } -"+"?[A-Z][a-l0-9][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=^])? { +"+"?[A-Z][a-l0-9][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|[=+])? { /* * piece move with rank or file disambiguator */ @@ -681,6 +687,7 @@ extern void CopyBoard P((Board to, Board from)); if(yyleng-skip > 4) /* [HGM] can have Shogi-style promotion */ cl.promoCharIn = yytext[yyleng-1-(yytext[yyleng-1]==')')]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.rtIn >= BOARD_HEIGHT || diff --git a/winboard/winboard.c b/winboard/winboard.c index 2ab9456..f818927 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -4318,7 +4318,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing); break; case PB_Queen: - promoChar = gameInfo.variant == VariantShogi ? '^' : PieceToChar(BlackQueen); + promoChar = gameInfo.variant == VariantShogi ? '+' : PieceToChar(BlackQueen); break; case PB_Rook: promoChar = PieceToChar(BlackRook); diff --git a/xboard.c b/xboard.c index 59796c7..67992f1 100644 --- a/xboard.c +++ b/xboard.c @@ -5431,7 +5431,7 @@ void PromotionCallback(w, client_data, call_data) } else if (strcmp(name, _("Knight")) == 0) { promoChar = 'n'; } else if (strcmp(name, _("Promote")) == 0) { - promoChar = '^'; + promoChar = '+'; } else if (strcmp(name, _("Defer")) == 0) { promoChar = '='; } else { -- 1.7.0.4