* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
'p', 'n', 'b', 'r', 'q', 'f', 'e', 'a', 'c', 'w', 'm',
'o', 'h', 'i', 'j', 'g', 'd', 'v', 'l', 's', 'u', 'k',
'x' };
+char pieceNickName[EmptySquare];
char PieceToChar(p)
ChessSquare p;
{
int i;
for(i=0; i< (int) EmptySquare; i++)
+ if(pieceNickName[i] == c) return (ChessSquare) i;
+ for(i=0; i< (int) EmptySquare; i++)
if(pieceToChar[i] == c) return (ChessSquare) i;
return EmptySquare;
}
{ /* [HGM] made dependent on CharToPiece to alow alternate piece letters */
ChessSquare piece = CharToPiece(whiteOnMove ? ToUpper(promoChar) : ToLower(promoChar) );
-
+ if(promoChar == '=') return whiteOnMove ? WhiteNonPromotion : BlackNonPromotion;
if(promoChar == NULLCHAR) return NormalMove;
switch(piece) {
int rf, ff;
int i, j, d, s, fs, rs, rt, ft, m;
int epfile = (signed char)board[EP_STATUS]; // [HGM] gamestate: extract ep status from board
+ int promoRank = gameInfo.variant == VariantMakruk ? 3 : 1;
for (rf = 0; rf < BOARD_HEIGHT; rf++)
for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) {
}
if (rf < BOARD_HEIGHT-1 && board[rf + 1][ff] == EmptySquare) {
callback(board, flags,
- rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove,
+ rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotionQueen : NormalMove,
rf, ff, rf + 1, ff, closure);
}
if (rf == 1 && board[2][ff] == EmptySquare &&
((flags & F_KRIEGSPIEL_CAPTURE) ||
BlackPiece(board[rf + 1][ff + s]))) {
callback(board, flags,
- rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove,
+ rf >= BOARD_HEIGHT-1-promoRank ? WhitePromotionQueen : NormalMove,
rf, ff, rf + 1, ff + s, closure);
}
if (rf == BOARD_HEIGHT-4) {
}
if (rf > 0 && board[rf - 1][ff] == EmptySquare) {
callback(board, flags,
- rf == 1 ? BlackPromotionQueen : NormalMove,
+ rf <= promoRank ? BlackPromotionQueen : NormalMove,
rf, ff, rf - 1, ff, closure);
}
if (rf == BOARD_HEIGHT-2 && board[BOARD_HEIGHT-3][ff] == EmptySquare &&
((flags & F_KRIEGSPIEL_CAPTURE) ||
WhitePiece(board[rf - 1][ff + s]))) {
callback(board, flags,
- rf == 1 ? BlackPromotionQueen : NormalMove,
+ rf <= promoRank ? BlackPromotionQueen : NormalMove,
rf, ff, rf - 1, ff + s, closure);
}
if (rf == 3) {
/* Shogi Pawn and Silver General: first the Pawn move, */
/* then the General continues like a Ferz */
+ case WhiteMan:
+ if(gameInfo.variant != VariantMakruk) goto commoner;
case SHOGI WhitePawn:
case SHOGI WhiteFerz:
if (rf < BOARD_HEIGHT-1 &&
if(piece != SHOGI WhitePawn) goto finishSilver;
break;
+ case BlackMan:
+ if(gameInfo.variant != VariantMakruk) goto commoner;
case SHOGI BlackPawn:
case SHOGI BlackFerz:
if (rf > 0 &&
case WhiteSilver:
case BlackSilver:
m++; // [HGM] superchess: use for Centaur
- case WhiteMan:
- case BlackMan:
+ commoner:
case SHOGI WhiteKing:
case SHOGI BlackKing:
case WhiteKing:
}
}
- if(gameInfo.variant == VariantFischeRandom) {
+ if(flags & F_FRC_TYPE_CASTLING) {
/* generate all potential FRC castling moves (KxR), ignoring flags */
/* [HGM] test if the Rooks we find have castling rights */
}
board[rt][ft] = board[rf][ff];
board[rf][ff] = EmptySquare;
- }
+ } else board[rt][ft] = ff; // [HGM] drop
/* For compatibility with ICS wild 9, we scan the board in the
order a1, a2, a3, ... b1, b2, ..., h8 to find the first king,
} else {
board[rt][ft] = captured;
}
- }
+ } else board[rt][ft] = EmptySquare; // [HGM] drop
return cl.fking < BOARD_RGHT ? cl.check : 1000; // [HGM] atomic: return 1000 if we have no king
}
+ChessMove LegalDrop(board, flags, piece, rt, ft)
+ Board board;
+ int flags;
+ ChessSquare piece;
+ int rt, ft;
+{ // [HGM] put drop legality testing in separate routine for clarity
+ int n;
+if(appData.debugMode) fprintf(debugFP, "LegalDrop: %d @ %d,%d)\n", piece, ft, rt);
+ if(board[rt][ft] != EmptySquare) return ImpossibleMove; // must drop to empty square
+ n = PieceToNumber(piece);
+ if(gameInfo.holdingsWidth == 0 || (flags & F_WHITE_ON_MOVE ? board[n][BOARD_WIDTH-1] : board[BOARD_HEIGHT-1-n][0]) != piece)
+ return ImpossibleMove; // piece not available
+ if(gameInfo.variant == VariantShogi) { // in Shogi lots of drops are forbidden!
+ if((piece == WhitePawn || piece == WhiteQueen) && rt == BOARD_HEIGHT-1 ||
+ (piece == BlackPawn || piece == BlackQueen) && rt == 0 ||
+ piece == WhiteKnight && rt > BOARD_HEIGHT-3 ||
+ piece == BlackKnight && rt < 2 ) return IllegalMove; // e.g. where dropped piece has no moves
+ if(piece == WhitePawn || piece == BlackPawn) {
+ int r;
+ for(r=1; r<BOARD_HEIGHT-1; r++)
+ 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( (piece == WhitePawn || piece == BlackPawn) &&
+ (rt == 0 || rt == BOARD_HEIGHT -1 ) )
+ return IllegalMove; /* no pawn drops on 1st/8th */
+ }
+if(appData.debugMode) fprintf(debugFP, "LegalDrop: %d @ %d,%d)\n", piece, ft, rt);
+ if (!(flags & F_IGNORE_CHECK) &&
+ CheckTest(board, flags, DROP_RANK, piece, rt, ft, FALSE) ) return IllegalMove;
+ return flags & F_WHITE_ON_MOVE ? WhiteDrop : BlackDrop;
+}
extern void LegalityTestCallback P((Board board, int flags, ChessMove kind,
int rf, int ff, int rt, int ft,
int flags;
int rf, ff, rt, ft, promoChar;
{
- LegalityTestClosure cl; ChessSquare piece = board[rf][ff], *castlingRights = board[CASTLING];
+ LegalityTestClosure cl; ChessSquare piece, *castlingRights = board[CASTLING];
+
+ if(rf == DROP_RANK) return LegalDrop(board, flags, ff, rt, ft);
+ piece = board[rf][ff];
if (appData.debugMode) {
int i;
piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */
cl.kind = promoChar == '=' ? IllegalMove : WhitePromotionKnight;
else /* promotion optional, default is promote */
- cl.kind = promoChar == '=' ? NormalMove : WhitePromotionQueen;
+ cl.kind = promoChar == '=' ? WhiteNonPromotion : WhitePromotionQueen;
} else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?
NormalMove : IllegalMove;
piece == BlackKnight && rt < 2 ) /* promotion obligatory */
cl.kind = promoChar == '=' ? IllegalMove : BlackPromotionKnight;
else /* promotion optional, default is promote */
- cl.kind = promoChar == '=' ? NormalMove : BlackPromotionQueen;
+ cl.kind = promoChar == '=' ? BlackNonPromotion : BlackPromotionQueen;
} else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?
NormalMove : IllegalMove;
(cl->ftIn == -1 || cl->ftIn == ft || wildCard)) {
cl->count++;
- cl->piece = board[rf][ff];
- cl->rf = rf;
- cl->ff = ff;
- cl->rt = wildCard ? cl->rtIn : rt;
- cl->ft = wildCard ? cl->ftIn : ft;
- cl->kind = kind;
+ if(cl->count == 1 || board[rt][ft] != EmptySquare) {
+ // [HGM] oneclick: if multiple moves, be sure we remember capture
+ cl->piece = board[rf][ff];
+ cl->rf = rf;
+ cl->ff = ff;
+ cl->rt = wildCard ? cl->rtIn : rt;
+ cl->ft = wildCard ? cl->ftIn : ft;
+ cl->kind = kind;
+ }
+ cl->captures += (board[cl->rt][cl->ft] != EmptySquare); // [HGM] oneclick: count captures
}
}
{
int illegal = 0; char c = closure->promoCharIn;
- closure->count = 0;
+ closure->count = closure->captures = 0;
closure->rf = closure->ff = closure->rt = closure->ft = 0;
closure->kind = ImpossibleMove;
if (appData.debugMode) {
closure->kind = c == '=' ? IllegalMove : WhitePromotionKnight;
else /* promotion optional, default is promote */
closure->kind = c == '=' ? NormalMove : WhitePromotionQueen;
-
+ if(c != '=') closure->promoCharIn = 'q';
} else closure->kind = (c == NULLCHAR || c == 'x' || c == '=') ?
NormalMove : IllegalMove;
} else {
closure->kind = c == '=' ? IllegalMove : BlackPromotionKnight;
else /* promotion optional, default is promote */
closure->kind = c == '=' ? NormalMove : BlackPromotionQueen;
-
+ if(c != '=') closure->promoCharIn = 'q';
} else closure->kind = (c == NULLCHAR || c == 'x' || c == '=') ?
NormalMove : IllegalMove;
}