X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=moves.c;h=6ccbb1c082d295a68447ada3bb6a942d8ee051ca;hb=4792abc3494f983650870624197e9af53e682bb2;hp=d66711387fb3f7203ded86d7eba715dbb76aa4c5;hpb=e6bbc0609a8fd2080b6274af55186a431b851210;p=xboard.git diff --git a/moves.c b/moves.c index d667113..6ccbb1c 100644 --- a/moves.c +++ b/moves.c @@ -428,6 +428,18 @@ void GenPseudoLegal(board, flags, callback, closure) } break; + /* Make Dragon-Horse also do Dababba moves outside Shogi, for better disambiguation in variant Fairy */ + case WhiteCardinal: + case BlackCardinal: + for (d = 0; d <= 1; d++) // Dababba moves that Rook cannot do + for (s = -2; s <= 2; s += 4) { + rt = rf + s * d; + ft = ff + s * (1 - d); + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue; + if (SameColor(board[rf][ff], board[rt][ft])) continue; + callback(board, flags, NormalMove, rf, ff, rt, ft, closure); + } + /* Shogi Dragon Horse has to continue with Wazir after Bishop */ case SHOGI WhiteCardinal: case SHOGI BlackCardinal: @@ -622,12 +634,60 @@ void GenPseudoLegal(board, flags, callback, closure) } } break; + + Amazon: + /* First do Bishop,then continue like Chancellor */ + for (rs = -1; rs <= 1; rs += 2) + for (fs = -1; fs <= 1; fs += 2) + for (i = 1;; i++) { + rt = rf + (i * rs); + ft = ff + (i * fs); + if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break; + if (SameColor(board[rf][ff], board[rt][ft])) break; + callback(board, flags, NormalMove, + rf, ff, rt, ft, closure); + if (board[rt][ft] != EmptySquare) break; + } + m++; + goto doRook; + + // Use Lance as Berolina / Spartan Pawn. + case WhiteLance: + if(gameInfo.variant == VariantSuper) goto Amazon; + if (rf < BOARD_HEIGHT-1 && BlackPiece(board[rf + 1][ff])) + callback(board, flags, + rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotion : NormalMove, + rf, ff, rf + 1, ff, closure); + for (s = -1; s <= 1; s += 2) { + if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && board[rf + 1][ff + s] == EmptySquare) + callback(board, flags, + rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotion : NormalMove, + rf, ff, rf + 1, ff + s, closure); + if (rf == 1 && ff + 2*s >= BOARD_LEFT && ff + 2*s < BOARD_RGHT && board[3][ff + 2*s] == EmptySquare ) + callback(board, flags, NormalMove, rf, ff, 3, ff + 2*s, closure); + } + break; + + case BlackLance: + if(gameInfo.variant == VariantSuper) goto Amazon; + if (rf > 0 && WhitePiece(board[rf - 1][ff])) + callback(board, flags, + rf <= promoRank ? BlackPromotion : NormalMove, + rf, ff, rf - 1, ff, closure); + for (s = -1; s <= 1; s += 2) { + if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT && board[rf - 1][ff + s] == EmptySquare) + callback(board, flags, + rf <= promoRank ? BlackPromotion : NormalMove, + rf, ff, rf - 1, ff + s, closure); + if (rf == BOARD_HEIGHT-2 && ff + 2*s >= BOARD_LEFT && ff + 2*s < BOARD_RGHT && board[rf-2][ff + 2*s] == EmptySquare ) + callback(board, flags, NormalMove, rf, ff, rf-2, ff + 2*s, closure); + } + break; + case WhiteFalcon: // [HGM] wild: for wildcards, self-capture symbolizes move to anywhere case BlackFalcon: case WhiteCobra: case BlackCobra: - case WhiteLance: - case BlackLance: callback(board, flags, NormalMove, rf, ff, rf, ff, closure); break; @@ -697,7 +757,7 @@ int GenLegal(board, flags, callback, closure) VOIDSTAR closure; { GenLegalClosure cl; - int ff, ft, k, left, right; + int ff, ft, k, left, right, swap; int ignoreCheck = (flags & F_IGNORE_CHECK) != 0; ChessSquare wKing = WhiteKing, bKing = BlackKing, *castlingRights = board[CASTLING]; @@ -794,10 +854,11 @@ int GenLegal(board, flags, callback, closure) } } - if(flags & F_FRC_TYPE_CASTLING) { + if((swap = gameInfo.variant == VariantSChess) || flags & F_FRC_TYPE_CASTLING) { /* generate all potential FRC castling moves (KxR), ignoring flags */ /* [HGM] test if the Rooks we find have castling rights */ + /* In S-Chess we generate RxK for allowed castlings, for gating at Rook square */ if ((flags & F_WHITE_ON_MOVE) != 0) { @@ -816,7 +877,7 @@ int GenLegal(board, flags, callback, closure) for(k=left; kpieceIn == EmptySquare || cl->pieceIn == board[rf][ff] @@ -1210,7 +1281,7 @@ void DisambiguateCallback(board, flags, kind, rf, ff, rt, ft, closure) cl->ft = wildCard ? cl->ftIn : ft; cl->kind = kind; } - cl->captures += (board[cl->rt][cl->ft] != EmptySquare); // [HGM] oneclick: count captures + cl->captures += (board[rt][ft] != EmptySquare); // [HGM] oneclick: count captures } } @@ -1248,6 +1319,15 @@ void Disambiguate(board, flags, closure) } if (c == 'x') c = NULLCHAR; // get rid of any 'x' (which should never happen?) + if(gameInfo.variant == VariantSChess && c && c != '=' && closure->piece != WhitePawn && closure->piece != BlackPawn) { + if(closure->piece < BlackPawn) { // white + if(closure->rf != 0) closure->kind = IllegalMove; // must be on back rank + if(board[PieceToNumber(CharToPiece(ToUpper(c)))][BOARD_WIDTH-2] == 0) closure->kind = ImpossibleMove;// must be in stock + } else { + if(closure->rf != BOARD_HEIGHT-1) closure->kind = IllegalMove; + if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(c)))][1] == 0) closure->kind = ImpossibleMove; + } + } else if(gameInfo.variant == VariantShogi) { /* [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) { @@ -1291,7 +1371,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(flags & F_WHITE_ON_MOVE ? ToUpper(c) : ToLower(c)) == EmptySquare) closure->kind = ImpossibleMove; // but we cannot handle non-existing piece types! if (closure->count > 1) { closure->kind = AmbiguousMove; @@ -1336,7 +1416,7 @@ void CoordsToAlgebraicCallback(board, flags, kind, rf, ff, rt, ft, closure) register CoordsToAlgebraicClosure *cl = (CoordsToAlgebraicClosure *) closure; - if (rt == cl->rt && ft == cl->ft && + if ((rt == cl->rt && ft == cl->ft || rt == rf && ft == ff) && // [HGM] null move matches any toSquare (board[rf][ff] == cl->piece || PieceToChar(board[rf][ff]) == '~' && (ChessSquare) (DEMOTED board[rf][ff]) == cl->piece) @@ -1455,9 +1535,9 @@ ChessMove CoordsToAlgebraic(board, flags, rf, ff, rt, ft, promoChar, out) ((ff == BOARD_WIDTH>>1 && (ft == BOARD_LEFT+2 || ft == BOARD_RGHT-2)) || (ff == (BOARD_WIDTH-1)>>1 && (ft == BOARD_LEFT+1 || ft == BOARD_RGHT-3)))) { if(ft==BOARD_LEFT+1 || ft==BOARD_RGHT-2) - safeStrCpy(out, "O-O", MOVE_LEN); + snprintf(out, MOVE_LEN, "O-O%c%c", promoChar ? '/' : 0, ToUpper(promoChar)); else - safeStrCpy(out, "O-O-O", MOVE_LEN); + snprintf(out, MOVE_LEN, "O-O-O%c%c", promoChar ? '/' : 0, ToUpper(promoChar)); /* This notation is always unambiguous, unless there are kings on both the d and e files, with "wild castling" @@ -1524,16 +1604,13 @@ ChessMove CoordsToAlgebraic(board, flags, rf, ff, rt, ft, promoChar, out) /* [HGM] in Shogi non-pawns can promote */ *outp++ = promoChar; // Don't bother to correct move type, return value is never used! } + else if (gameInfo.variant == VariantSChess && promoChar) { // and in S-Chess we have gating + *outp++ = '/'; + *outp++ = ToUpper(promoChar); + } *outp = NULLCHAR; return cl.kind; - - /* [HGM] Always long notation for fairies we don't know */ - case WhiteFalcon: - case BlackFalcon: - case WhiteLance: - case BlackLance: - case WhiteGrasshopper: - case BlackGrasshopper: + case EmptySquare: /* Moving a nonexistent piece */ break; @@ -1548,13 +1625,19 @@ ChessMove CoordsToAlgebraic(board, flags, rf, ff, rt, ft, promoChar, out) a piece of the same color. */ outp = out; + c = 0; if (piece != EmptySquare && piece != WhitePawn && piece != BlackPawn) { + int r, f; + for(r=0; r