MovesFromString (Board board, int flags, int f, int r, int tx, int ty, int angle, char *desc, MoveCallback cb, VOIDSTAR cl)
{
char buf[80], *p = desc, *atom = NULL;
- int mine, his, dir, bit, occup, i, promoRank = -1;
+ int mine, his, dir, bit, occup, i, ep, promoRank = -1;
ChessMove promo= NormalMove; ChessSquare pc = board[r][f];
+ if(pc == DarkSquare) return; // this is not a piece, but a 'hole' in the board
if(flags & F_WHITE_ON_MOVE) his = 2, mine = 1; else his = 1, mine = 2;
if(pc == WhitePawn || pc == WhiteLance) promo = WhitePromotion, promoRank = BOARD_HEIGHT-1; else
if(pc == BlackPawn || pc == BlackLance) promo = BlackPromotion, promoRank = 0;
for(dir=0, bit=1; dir<8; dir++, bit += bit) { // loop over directions
int i = expo, j = skip, hop = mode, vx, vy, loop = 0;
if(!(bit & dirSet)) continue; // does not move in this direction
- if(dy != 1) j = 0; //
+ if(dy != 1 || mode & 1024) j = 0; //
vx = dx*rot[dir][0] + dy*rot[dir][1]; // rotate step vector
vy = dx*rot[dir][2] + dy*rot[dir][3];
if(tx < 0) x = f, y = r; // start square
if(y < 0 || y >= BOARD_HEIGHT) break; // vertically off-board: always done
if(x < BOARD_LEFT) { if(mode & 128) x += BOARD_RGHT - BOARD_LEFT, loop++; else break; }
if(x >= BOARD_RGHT) { if(mode & 128) x -= BOARD_RGHT - BOARD_LEFT, loop++; else break; }
+ if(board[y][x] == DarkSquare) break; // black squares are supposed to be off board
if(j) { j--; continue; } // skip irrespective of occupation
if(!jump && board[y - vy + vy/2][x - vx + vx/2] != EmptySquare) break; // blocked
if(jump > 1 && board[y - vy + vy/2][x - vx + vx/2] == EmptySquare) break; // no hop
continue;
}
if(hop & 32+64) { if(occup != 4) { if(hop & 64 && i != 1) i = 2; hop &= 31; } continue; } // hopper
- if(mode & 8 && y == board[EP_RANK] && occup == 4 && board[EP_FILE] == x) { // to e.p. square
+ ep = board[EP_RANK];
+ if(mode & 8 && occup == 4 && board[EP_FILE] == x && (y == (ep & 127) || y - vy == ep - 128)) { // to e.p. square (or 2nd e.p. square)
cb(board, flags, mine == 1 ? WhiteCapturesEnPassant : BlackCapturesEnPassant, r, f, y, x, cl);
}
if(mode & 1024) { // castling
i = 2; // kludge to elongate move indefinitely
if(occup == 4) continue; // skip empty squares
- if(x == BOARD_LEFT && board[y][x] == initialPosition[y][x]) // reached initial corner piece
+ if((x == BOARD_LEFT + skip || x > BOARD_LEFT + skip && vx < 0 && board[y][x-1-skip] == DarkSquare)
+ && board[y][x] == initialPosition[y][x]) { // reached initial corner piece
+ if(pc != WhiteKing && pc != BlackKing) { // non-royal castling (to be entered as two-leg move via 'Rook')
+ if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX < f)
+ legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f - expo, cl), legNr >>= 1;
+ } else
cb(board, flags, mine == 1 ? WhiteQueenSideCastle : BlackQueenSideCastle, r, f, y, f - expo, cl);
- if(x == BOARD_RGHT-1 && board[y][x] == initialPosition[y][x])
+ }
+ if((x == BOARD_RGHT-1-skip || x < BOARD_RGHT-1-skip && vx > 0 && board[y][x+1+skip] == DarkSquare)
+ && board[y][x] == initialPosition[y][x]) {
+ if(pc != WhiteKing && pc != BlackKing) {
+ if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX > f)
+ legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f + expo, cl), legNr >>= 1;
+ } else
cb(board, flags, mine == 1 ? WhiteKingSideCastle : BlackKingSideCastle, r, f, y, f + expo, cl);
+ }
break;
}
if(mode & 16 && (board[y][x] == WhiteKing || board[y][x] == BlackKing)) break; // tame piece, cannot capture royal
board[rf][ft] = captured;
board[rt][ft] = EmptySquare;
} else {
- if(saveKill >= 0) board[killY][killX] = trampled, killX = saveKill;
+ if(saveKill >= 0) board[killY][killX = saveKill] = trampled;
board[rt][ft] = captured;
}
board[EP_STATUS] = ep;
/* [HGM] Shogi promotions. '=' means defer */
if(rf != DROP_RANK && cl.kind == NormalMove) {
ChessSquare piece = board[rf][ff];
+ int zone = BOARD_HEIGHT/3 + (BOARD_HEIGHT == 8);
if(promoChar == PieceToChar(BlackQueen)) promoChar = NULLCHAR; /* [HGM] Kludge */
if(promoChar == 'd' && (piece == WhiteRook || piece == BlackRook) ||
return CharToPiece(promoChar) == EmptySquare ? ImpossibleMove : IllegalMove;
else if(flags & F_WHITE_ON_MOVE) {
if( (int) piece < (int) WhiteWazir &&
- (rf >= BOARD_HEIGHT - BOARD_HEIGHT/3 || rt >= BOARD_HEIGHT - BOARD_HEIGHT/3) ) {
+ (rf >= BOARD_HEIGHT - zone || rt >= BOARD_HEIGHT - zone) ) {
if( (piece == WhitePawn || piece == WhiteQueen) && rt > BOARD_HEIGHT-2 ||
piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */
cl.kind = promoChar == '=' ? IllegalMove : WhitePromotion;
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( (int) piece < (int) BlackWazir && (rf < zone || rt < zone) ) {
if( (piece == BlackPawn || piece == BlackQueen) && rt < 1 ||
piece == BlackKnight && rt < 2 ) /* promotion obligatory */
cl.kind = promoChar == '=' ? IllegalMove : BlackPromotion;
/* [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;
+ int zone = BOARD_HEIGHT/3 + (BOARD_HEIGHT == 8);
if (c == 'd' && (piece == WhiteRook || piece == BlackRook) ||
c == 'h' && (piece == WhiteBishop || piece == BlackBishop) ||
c == 'g' && (piece <= WhiteFerz || piece <= BlackFerz && piece >= BlackPawn) )
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)) ) {
+ (closure->rf >= BOARD_HEIGHT-zone || closure->rt >= BOARD_HEIGHT-zone) ) {
if( (piece == WhitePawn || piece == WhiteQueen) && closure->rt > BOARD_HEIGHT-2 ||
piece == WhiteKnight && closure->rt > BOARD_HEIGHT-3) /* promotion mandatory */
closure->kind = c == '=' ? IllegalMove : WhitePromotion;
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( (int) piece < (int) BlackWazir && (closure->rf < zone || closure->rt < zone) ) {
if( (piece == BlackPawn || piece == BlackQueen) && closure->rt < 1 ||
piece == BlackKnight && closure->rt < 2 ) /* promotion obligatory */
closure->kind = c == '=' ? IllegalMove : BlackPromotion;