&& !SameColor(board[rf][ff], board[rt][ft]))
callback(board, flags, NormalMove,
rf, ff, rt, ft, closure);
+ if(gameInfo.variant != VariantFairy && gameInfo.variant != VariantGreat) continue;
+ rt = rf + rs; // in unknown variant we assume Modern Elephant, which can also do one step
+ ft = ff + fs;
+ if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)
+ && !SameColor(board[rf][ff], board[rt][ft]))
+ callback(board, flags, NormalMove,
+ rf, ff, rt, ft, 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:
}
break;
+ /* Make Dragon-King Dababba & Rook-like outside Shogi, for better disambiguation in variant Fairy */
+ case WhiteDragon:
+ case BlackDragon:
+ 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 || board[rf+rt>>1][ff+ft>>1] == EmptySquare) continue;
+ if (SameColor(board[rf][ff], board[rt][ft])) continue;
+ callback(board, flags, NormalMove, rf, ff, rt, ft, closure);
+ }
+ goto doRook;
+
/* Shogi Dragon King has to continue as Ferz after Rook moves */
case SHOGI WhiteDragon:
case SHOGI BlackDragon:
case SHOGI BlackRook:
case WhiteRook:
case BlackRook:
+ doRook:
for (d = 0; d <= 1; d++)
for (s = -1; s <= 1; s += 2)
for (i = 1;; i++) {
}
}
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;
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];
}
}
- 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) {
for(k=left; k<right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = NoRights;
if(ft != NoRights && board[0][ft] == WhiteRook)
- callback(board, flags, WhiteHSideCastleFR, 0, ff, 0, ft, closure);
+ callback(board, flags, WhiteHSideCastleFR, 0, swap ? ft : ff, 0, swap ? ff : ft, closure);
ft = castlingRights[1]; /* Rook file if we have A-side rights */
left = BOARD_LEFT+2;
for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = NoRights;
if(ft != NoRights && board[0][ft] == WhiteRook)
- callback(board, flags, WhiteASideCastleFR, 0, ff, 0, ft, closure);
+ callback(board, flags, WhiteASideCastleFR, 0, swap ? ft : ff, 0, swap ? ff : ft, closure);
}
} else {
ff = castlingRights[5]; /* King file if we have any rights */
for(k=left; k<right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = NoRights;
if(ft != NoRights && board[BOARD_HEIGHT-1][ft] == BlackRook)
- callback(board, flags, BlackHSideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);
+ callback(board, flags, BlackHSideCastleFR, BOARD_HEIGHT-1, swap ? ft : ff, BOARD_HEIGHT-1, swap ? ff : ft, closure);
ft = castlingRights[4]; /* Rook file if we have A-side rights */
left = BOARD_LEFT+2;
for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */
if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = NoRights;
if(ft != NoRights && board[BOARD_HEIGHT-1][ft] == BlackRook)
- callback(board, flags, BlackASideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);
+ callback(board, flags, BlackASideCastleFR, BOARD_HEIGHT-1, swap ? ft : ff, BOARD_HEIGHT-1, swap ? ff : ft, closure);
}
}
if(board[r][ft] == piece) return IllegalMove; // or there already is a Pawn in file
// should still test if we mate with this Pawn
}
+ } else if(gameInfo.variant == VariantSChess) { // only back-rank drops
+ if (rt != (piece < BlackPawn ? 0 : BOARD_HEIGHT-1)) return IllegalMove;
} else {
if( (piece == WhitePawn || piece == BlackPawn) &&
(rt == 0 || rt == BOARD_HEIGHT -1 ) )
for(i=0; i<6; i++) fprintf(debugFP, "%d ", castlingRights[i]);
fprintf(debugFP, "Legality test? %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);
}
- /* [HGM] Lance, Cobra and Falcon are wildcard pieces; consider all their moves legal */
+ /* [HGM] Cobra and Falcon are wildcard pieces; consider all their moves legal */
/* (perhaps we should disallow moves that obviously leave us in check?) */
if(piece == WhiteFalcon || piece == BlackFalcon ||
- piece == WhiteCobra || piece == BlackCobra ||
- piece == WhiteLance || piece == BlackLance)
+ piece == WhiteCobra || piece == BlackCobra)
return CheckTest(board, flags, rf, ff, rt, ft, FALSE) ? IllegalMove : NormalMove;
cl.rf = rf;
return(IllegalMove); // [HGM] losers: if there are legal captures, non-capts are illegal
if(promoChar == 'x') promoChar = NULLCHAR; // [HGM] is this ever the case?
+ if(gameInfo.variant == VariantSChess && promoChar && promoChar != '=' && board[rf][ff] != WhitePawn && board[rf][ff] != BlackPawn) {
+ if(board[rf][ff] < BlackPawn) { // white
+ if(rf != 0) return IllegalMove; // must be on back rank
+ if(board[PieceToNumber(CharToPiece(ToUpper(promoChar)))][BOARD_WIDTH-2] == 0) return ImpossibleMove;// must be in stock
+ } else {
+ if(rf != BOARD_HEIGHT-1) return IllegalMove;
+ if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(promoChar)))][1] == 0) return ImpossibleMove;
+ }
+ } else
if(gameInfo.variant == VariantShogi) {
/* [HGM] Shogi promotions. '=' means defer */
if(rf != DROP_RANK && cl.kind == NormalMove) {
ChessSquare piece = board[rf][ff];
if(promoChar == PieceToChar(BlackQueen)) promoChar = NULLCHAR; /* [HGM] Kludge */
- if(promoChar != NULLCHAR && promoChar != '+' && promoChar != '=' &&
- ToUpper(PieceToChar(PROMOTED piece)) != ToUpper(promoChar) )
- cl.kind = IllegalMove;
+ 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
+if(appData.debugMode)fprintf(debugFP,"SHOGI promoChar = %c\n", 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 &&
(rf >= BOARD_HEIGHT*2/3 || rt >= BOARD_HEIGHT*2/3) ) {
if( (piece == WhitePawn || piece == WhiteQueen) && rt > BOARD_HEIGHT-2 ||
piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */
- cl.kind = promoChar == '=' ? IllegalMove : WhitePromotion;
- else /* promotion optional, default is promote */
- cl.kind = promoChar == '=' ? WhiteNonPromotion : WhitePromotion;
-
- } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?
- NormalMove : IllegalMove;
+ cl.kind = promoChar == '=' ? IllegalMove : WhitePromotion;
+ else /* promotion optional, default is defer */
+ 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 promote */
- cl.kind = promoChar == '=' ? BlackNonPromotion : BlackPromotion;
-
- } else cl.kind = (promoChar == NULLCHAR || promoChar == '=') ? NormalMove : IllegalMove;
+ cl.kind = promoChar == '=' ? IllegalMove : BlackPromotion;
+ else /* promotion optional, default is defer */
+ cl.kind = promoChar == '+' ? BlackPromotion : BlackNonPromotion;
+ } else cl.kind = promoChar == '+' ? IllegalMove : NormalMove;
}
}
} else
if (promoChar != NULLCHAR) {
if(promoChar == '=') cl.kind = IllegalMove; else // [HGM] shogi: no deferred promotion outside Shogi
if (cl.kind == WhitePromotion || cl.kind == BlackPromotion) {
- if(CharToPiece(promoChar) == EmptySquare) cl.kind = ImpossibleMove; // non-existing piece
+ if(CharToPiece(flags & F_WHITE_ON_MOVE ? ToUpper(promoChar) : ToLower(promoChar)) == EmptySquare)
+ cl.kind = ImpossibleMove; // non-existing piece
} else {
cl.kind = IllegalMove;
}
// [HGM] wild: for wild-card pieces rt and rf are dummies
if(piece == WhiteFalcon || piece == BlackFalcon ||
- piece == WhiteCobra || piece == BlackCobra ||
- piece == WhiteLance || piece == BlackLance)
+ piece == WhiteCobra || piece == BlackCobra)
wildCard = TRUE;
if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff]
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
}
}
}
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, NULL 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 != NULLCHAR && c != '+' && c != '=' &&
- ToUpper(PieceToChar(PROMOTED piece)) != ToUpper(c) )
- closure->kind = IllegalMove; // the only allowed cases are '+', '=' and the promoted partner.
+ 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
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)) ) {
if( (piece == WhitePawn || piece == WhiteQueen) && closure->rt > BOARD_HEIGHT-2 ||
piece == WhiteKnight && closure->rt > BOARD_HEIGHT-3) /* promotion mandatory */
- closure->kind = c == '=' ? IllegalMove : WhitePromotion;
- else /* promotion optional, default is promote */
- closure->kind = c == '=' ? WhiteNonPromotion : WhitePromotion;
- } else closure->kind = (c == NULLCHAR || c == '=') ? NormalMove : IllegalMove;
+ closure->kind = c == '=' ? IllegalMove : WhitePromotion;
+ else /* promotion optional, default is defer */
+ 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 promote */
- closure->kind = c == '=' ? BlackNonPromotion : BlackPromotion;
- } else closure->kind = (c == NULLCHAR || c == '=') ? NormalMove : IllegalMove;
+ closure->kind = c == '=' ? IllegalMove : BlackPromotion;
+ else /* promotion optional, default is defer */
+ closure->kind = c == '+' ? BlackPromotion : BlackNonPromotion;
+ } else closure->kind = c == '+' ? IllegalMove : NormalMove;
}
}
- c = (closure->kind == WhitePromotion || closure->kind == BlackPromotion) ? '+' : NULLCHAR;
+ 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) {
- if(c == NULLCHAR) c = 'q'; // even in Shatranj, Courier, Makruk, as Apply move corrects this to Ferz (how messy!)
+ if(c == NULLCHAR) { // missing promoChar on mandatory promotion; use default for variant
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
+ c = PieceToChar(BlackFerz);
+ else if(gameInfo.variant == VariantGreat)
+ c = PieceToChar(BlackMan);
+ else
+ c = PieceToChar(BlackQueen);
+ } else if(c == '=') closure->kind = IllegalMove; // no deferral outside Shogi
} 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 != NULLCHAR && CharToPiece(c) == EmptySquare) closure->kind = ImpossibleMove; // but we cannot handle non-existing piece types!
+ 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;
}
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)
((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"
if(rt+ONE <= '9')
*outp++ = rt + ONE;
else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }
- *outp = NULLCHAR;
if (gameInfo.variant == VariantShogi) {
/* [HGM] in Shogi non-pawns can promote */
- if(flags & F_WHITE_ON_MOVE) {
- if( (int) cl.piece < (int) WhiteWazir &&
- (rf >= BOARD_HEIGHT-(BOARD_HEIGHT/3) || rt >= BOARD_HEIGHT-(BOARD_HEIGHT/3)) ) {
- if( (piece == WhitePawn || piece == WhiteQueen) && rt > BOARD_HEIGHT-2 ||
- piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */
- cl.kind = promoChar == '=' ? IllegalMove : WhitePromotion;
- else cl.kind = WhitePromotion; /* promotion optional */
- } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?
- NormalMove : IllegalMove;
- } else {
- if( (int) cl.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 cl.kind = BlackPromotion; /* promotion optional */
- } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?
- NormalMove : IllegalMove;
- }
- if(cl.kind == WhitePromotion || cl.kind == BlackPromotion) {
- /* for optional promotions append '+' or '=' */
- if(promoChar == '=') {
- *outp++ = '=';
- cl.kind = NormalMove;
- } else *outp++ = '+';
- *outp = NULLCHAR;
- } else if(cl.kind == IllegalMove) {
- /* Illegal move specifies any given promotion */
- if(promoChar != NULLCHAR && promoChar != 'x') {
- *outp++ = '=';
- *outp++ = ToUpper(promoChar);
- *outp = NULLCHAR;
- }
- }
+ *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;
a piece of the same color.
*/
outp = out;
+ c = 0;
if (piece != EmptySquare && piece != WhitePawn && piece != BlackPawn) {
+ int r, f;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<=BOARD_RGHT; f++)
+ c += (board[r][f] == piece); // count on-board pieces of given type
*outp++ = ToUpper(PieceToChar(piece));
}
+ if(c != 1) { // [HGM] but if there is only one piece of the mentioned type, no from-square, thank you!
*outp++ = ff + AAA;
if(rf+ONE <= '9')
*outp++ = rf + ONE;
else { *outp++ = (rf+ONE-'0')/10 + '0';*outp++ = (rf+ONE-'0')%10 + '0'; }
+ }
if (board[rt][ft] != EmptySquare) *outp++ = 'x';
*outp++ = ft + AAA;
if(rt+ONE <= '9')