move_make_promotions(), clean move_do(), pos_gen_pseudomoves()
This commit is contained in:
@@ -52,6 +52,7 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
||||
color_t us = pos->turn, them = OPPONENT(us);
|
||||
square_t from = move_from(move), to = move_to(move);
|
||||
piece_t piece = pos->board[from];
|
||||
piece_t captured = pos->board[to];
|
||||
piece_type_t ptype = PIECE(piece);
|
||||
color_t pcolor = COLOR(piece);
|
||||
piece_t new_piece = piece;
|
||||
@@ -60,6 +61,7 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
||||
++pos->plycount;
|
||||
pos->en_passant = SQUARE_NONE;
|
||||
pos->turn = them;
|
||||
pos->captured = captured;
|
||||
|
||||
bug_on(pcolor != us);
|
||||
|
||||
@@ -68,9 +70,9 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
||||
new_piece = MAKE_PIECE(move_promoted(move), us);
|
||||
}
|
||||
|
||||
if (is_capture(move)) {
|
||||
if (captured != EMPTY) {
|
||||
pos->clock_50 = 0;
|
||||
pos->captured = pos->board[to]; /* save capture info */
|
||||
//pos->captured = pos->board[to]; /* save capture info */
|
||||
bug_on(pos->board[to] == EMPTY || COLOR(pos->captured) != them);
|
||||
pos_clr_sq(pos, to); /* clear square */
|
||||
} else if (is_castle(move)) { /* handle rook move */
|
||||
@@ -88,7 +90,7 @@ pos_t *move_do(pos_t *pos, const move_t move) //, state_t *state)
|
||||
} else if (ptype == PAWN) { /* pawn non capture or e.p. */
|
||||
pos->clock_50 = 0;
|
||||
if (is_dpush(move)) /* if pawn double push, set e.p. */
|
||||
pos->en_passant = pawn_push_up(from, us);
|
||||
pos->en_passant = from + sq_up(us);
|
||||
else if (is_enpassant(move)) { /* clear grabbed pawn */
|
||||
square_t grabbed = pawn_push_up(to, them);
|
||||
pos_clr_sq(pos, grabbed);
|
||||
@@ -160,13 +162,13 @@ pos_t *move_undo(pos_t *pos, const move_t move)//, const state_t *state)
|
||||
if (is_promotion(move))
|
||||
piece = MAKE_PIECE(PAWN, us);
|
||||
|
||||
pos_clr_sq(pos, to); /* always clear "to" and set "from" */
|
||||
pos_set_sq(pos, from, piece);
|
||||
pos_clr_sq(pos, to); /* always clear "to" ... */
|
||||
pos_set_sq(pos, from, piece); /* ... and set "from" */
|
||||
|
||||
if (PIECE(piece) == KING)
|
||||
pos->king[us] = from;
|
||||
|
||||
if (is_capture(move)) {
|
||||
if (pos->captured != EMPTY) {
|
||||
pos_set_sq(pos, to, pos->captured); /* restore captured piece */
|
||||
} else if (is_castle(move)) { /* make reverse rook move */
|
||||
square_t rookfrom, rookto;
|
||||
|
338
src/move-gen.c
338
src/move-gen.c
@@ -40,25 +40,32 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move)
|
||||
square_t from = move_from(move), to = move_to(move);
|
||||
square_t king = pos->king[us];
|
||||
bitboard_t kingbb = pos->bb[us][KING];
|
||||
bitboard_t occ = pos_occ(pos);
|
||||
u64 pinned = mask(from) & pos->blockers;
|
||||
|
||||
/* (1) - King
|
||||
* For castling, we already tested intermediate squares attacks
|
||||
* in pseudo move generation, so we only care destination square here.
|
||||
* Attention: We need to exclude king from occupation bitboard !
|
||||
/* (1) - Castling & King
|
||||
* For castling, we need to check intermediate squares attacks only.
|
||||
* Attention: To test if K is in check after moving, we need to exclude
|
||||
* king from occupation bitboard (to catch king moving away from checker
|
||||
* on same line) !
|
||||
*/
|
||||
if (is_castle(move)) {
|
||||
square_t dir = to > from? 1: -1;
|
||||
if (sq_attackers(pos, occ, from + dir, them))
|
||||
return false;
|
||||
}
|
||||
if (from == king) {
|
||||
bitboard_t occ = pos_occ(pos) ^ kingbb;
|
||||
return !sq_attackers(pos, occ, to, them);
|
||||
return !sq_attackers(pos, occ ^ kingbb, to, them);
|
||||
}
|
||||
|
||||
/* (2) - King is in check
|
||||
* Double-check is already handled, as only K moves were generated.
|
||||
* Double-check is already handled in (1), as only K moves were generated
|
||||
* by pseudo legal move generator.
|
||||
* Here, allowed dest squares are only on King-checker line, or on checker
|
||||
* square.
|
||||
* attacker.
|
||||
* Special cases:
|
||||
* e.p., legal if the taken pawn is giving check
|
||||
* e.p., legal if the grabbed pawn is giving check
|
||||
* pinned piece: always illegal
|
||||
*/
|
||||
if (pos->checkers) {
|
||||
@@ -68,8 +75,9 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move)
|
||||
return false;
|
||||
square_t checker = ctz64(pos->checkers);
|
||||
if (is_enpassant(move)) {
|
||||
return pawn_push_up(pos->en_passant, them) == checker;
|
||||
return pos->en_passant + sq_up(them) == checker;
|
||||
}
|
||||
return true;
|
||||
bitboard_t between = bb_between[king][checker] | pos->checkers;
|
||||
return mask(to) & between;
|
||||
}
|
||||
@@ -77,28 +85,25 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move)
|
||||
/* (3) - pinned pieces
|
||||
* We verify here that pinned piece P stays on line King-P.
|
||||
*/
|
||||
//if (mask(from) & pos->blockers & pos->bb[us][ALL_PIECES]) {
|
||||
if (pinned) {
|
||||
bitboard_t line = bb_line[from][king];
|
||||
return line & mask(to); /* to is not on pin line */
|
||||
if (mask(from) & pos->blockers) {
|
||||
return bb_line[from][king] & mask(to); /* is to on pinner line ? */
|
||||
}
|
||||
|
||||
/* (4) - En-passant
|
||||
* pinned pieces are already handled.
|
||||
* One case is left: when the two "disappearing" pawns would discover
|
||||
* a R/Q check.
|
||||
* pinned pieces are handled in pinned section.
|
||||
* One case not handled anywhere else: when the two "disappearing" pawns
|
||||
* would discover a R/Q horizontal check.
|
||||
*/
|
||||
if (is_enpassant(move)) {
|
||||
bitboard_t rank5 = us == WHITE? RANK_5bb: RANK_4bb;
|
||||
|
||||
if ((pos->bb[us][KING] & rank5)) {
|
||||
bitboard_t exclude = mask(pos->en_passant + sq_up(them)) | mask(from);
|
||||
bitboard_t exclude = mask(pos->en_passant - sq_up(us)) | mask(from);
|
||||
bitboard_t rooks = (pos->bb[them][ROOK] | pos->bb[them][QUEEN]) & rank5;
|
||||
|
||||
bitboard_t occ = pos_occ(pos) ^ exclude;
|
||||
while (rooks) {
|
||||
square_t rook = bb_next(&rooks);
|
||||
if (hyperbola_rank_moves(occ, rook) & kingbb)
|
||||
if (hyperbola_rank_moves(occ ^ exclude, rook) & kingbb)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -152,6 +157,27 @@ movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *de
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* gen_pseudo_king() - generate king pseudo-legal moves.
|
||||
* @pos: position
|
||||
* @movelist: &movelist_t array to store pseudo-moves
|
||||
*
|
||||
*/
|
||||
static inline __unused move_t *gen_pseudo_king(move_t *moves, square_t from,
|
||||
bitboard_t mask)
|
||||
{
|
||||
//color_t us = pos->turn;
|
||||
//square_t from = pos->king[us];
|
||||
//bitboard_t not_my_pieces = ~pos->bb[us][ALL_PIECES];
|
||||
bitboard_t to_bb = bb_king_moves(mask, from);
|
||||
square_t to;
|
||||
while (moves) {
|
||||
to = bb_next(&to_bb);
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_gen_check_pseudomoves() - generate position pseudo-legal moves when in check
|
||||
* @pos: position
|
||||
@@ -176,6 +202,48 @@ movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *de
|
||||
* @Return: The total number of moves.
|
||||
*/
|
||||
|
||||
/**
|
||||
* gen_pseudo_escape() - generate position pseudo-legal moves when in check
|
||||
* @pos: square_t king position
|
||||
* @mask: possible destinations to consider
|
||||
* @moves: &move_t array to store pseudo-moves
|
||||
*
|
||||
* Generate all @pos pseudo moves for player-to-move, when in check.
|
||||
* @movelist is filled with the moves.
|
||||
*
|
||||
* If king is doubles-checked, only King moves will be generated.
|
||||
* Otherwise, only moves where destination in between King or checker, or checker
|
||||
* square.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* static void __always_inline gen_pseudo_escape(pos_t *pos, movelist_t *movelist)
|
||||
* {
|
||||
* color_t us = pos->turn;
|
||||
* color_t them = OPPONENT(us);
|
||||
* square_t king = pos->king[us];
|
||||
*
|
||||
* gen_pseudo_king(pos, movelist);
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* move_make_promotions() - generate all promotions for given pawn and dest.
|
||||
* @moves: &move_t array where to store moves
|
||||
* @from: pawn position
|
||||
* @to: promotion square
|
||||
*
|
||||
* Generate all (Q/R/B/N) promotion moves on @to for pawn @from.
|
||||
*
|
||||
* @Return: New @moves (incremented by 4).
|
||||
*/
|
||||
static inline move_t *move_make_promotions(move_t *moves, square_t from, square_t to)
|
||||
{
|
||||
for (piece_type_t pt = QUEEN; pt >= KNIGHT; --pt)
|
||||
*moves++ = move_make_promote(from, to, pt);
|
||||
return moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* pos_gen_pseudomoves() - generate position pseudo-legal moves
|
||||
@@ -206,60 +274,88 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
||||
color_t them = OPPONENT(us);
|
||||
|
||||
bitboard_t my_pieces = pos->bb[us][ALL_PIECES];
|
||||
bitboard_t not_my_pieces = ~my_pieces;
|
||||
bitboard_t enemy_pieces = pos->bb[them][ALL_PIECES];
|
||||
bitboard_t dest_squares = ~my_pieces;
|
||||
bitboard_t occ = my_pieces | enemy_pieces;
|
||||
bitboard_t empty = ~occ;
|
||||
|
||||
bitboard_t movebits, from_pawns;
|
||||
bitboard_t tmp1, tmp2;
|
||||
bitboard_t from_bb, to_bb;
|
||||
bitboard_t tmp_bb;
|
||||
move_t *moves = movelist->move;
|
||||
int *nmoves = &movelist->nmoves;
|
||||
int from, to;
|
||||
//int *nmoves = &movelist->nmoves;
|
||||
square_t from, to;
|
||||
square_t king = pos->king[us];
|
||||
|
||||
*nmoves = 0;
|
||||
//*nmoves = 0;
|
||||
|
||||
/* king - MUST BE FIRST (we stop if doubler check) */
|
||||
from = pos->king[us];
|
||||
movebits = bb_king_moves(not_my_pieces, from);
|
||||
bit_for_each64(to, tmp1, movebits & empty) {
|
||||
moves[(*nmoves)++] = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp1, movebits & enemy_pieces) {
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
to_bb = bb_king_moves(dest_squares, king);
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
*moves++ = move_make(king, to);
|
||||
}
|
||||
|
||||
if (popcount64(pos->checkers) > 1) /* double check, we stop here */
|
||||
return *nmoves;
|
||||
if (bb_multiple(pos->checkers)) /* double check, we stop here */
|
||||
goto finish;
|
||||
|
||||
if (pos->checkers) {
|
||||
/* one checker: we limit destination squares to line between
|
||||
* checker and king + checker square (think: knight).
|
||||
*/
|
||||
square_t checker = ctz64(pos->checkers);
|
||||
dest_squares &= bb_between[king][checker] | pos->checkers;
|
||||
enemy_pieces &= dest_squares;
|
||||
} else {
|
||||
/* no checker: castling moves
|
||||
* Attention ! Castling flags are assumed correct
|
||||
*/
|
||||
bitboard_t rel_rank1 = bb_rel_rank(RANK_1, us);
|
||||
//square_t from_square[2] = { E1, E8 }; /* verify king is on E1/E8 */
|
||||
//bug_on(can_castle(pos->castle, us) && from != from_square[us]);
|
||||
/* For castle, we check the opponent attacks on squares between from and to.
|
||||
* To square attack check will be done in gen_is_legal.
|
||||
*/
|
||||
if (can_oo(pos->castle, us)) {
|
||||
bitboard_t occmask = rel_rank1 & (FILE_Fbb | FILE_Gbb);
|
||||
if (!(occ & occmask)) {
|
||||
*moves++ = move_make_flags(king, king + 2, M_CASTLE_K);
|
||||
}
|
||||
}
|
||||
if (can_ooo(pos->castle, us)) {
|
||||
bitboard_t occmask = rel_rank1 & (FILE_Bbb | FILE_Cbb | FILE_Dbb);
|
||||
if (!(occ & occmask)) { // &&
|
||||
*moves++ = move_make_flags(king, king - 2, M_CASTLE_Q);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* sliding pieces */
|
||||
bit_for_each64(from, tmp1, pos->bb[us][BISHOP] | pos->bb[us][QUEEN]) {
|
||||
movebits = hyperbola_bishop_moves(occ, from) & not_my_pieces;
|
||||
bit_for_each64(to, tmp2, movebits & empty) {
|
||||
moves[(*nmoves)++] = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp2, movebits & enemy_pieces) {
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
from_bb = pos->bb[us][BISHOP] | pos->bb[us][QUEEN];
|
||||
while (from_bb) {
|
||||
from = bb_next(&from_bb);
|
||||
to_bb = hyperbola_bishop_moves(occ, from) & dest_squares;
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
}
|
||||
bit_for_each64(from, tmp1, pos->bb[us][ROOK] | pos->bb[us][QUEEN]) {
|
||||
movebits = hyperbola_rook_moves(occ, from) & not_my_pieces;
|
||||
bit_for_each64(to, tmp2, movebits & empty) {
|
||||
moves[(*nmoves)++] = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp2, movebits & enemy_pieces) {
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
from_bb = pos->bb[us][ROOK] | pos->bb[us][QUEEN];
|
||||
while (from_bb) {
|
||||
from = bb_next(&from_bb);
|
||||
to_bb = hyperbola_rook_moves(occ, from) & dest_squares;
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
/* knight */
|
||||
bit_for_each64(from, tmp1, pos->bb[us][KNIGHT]) {
|
||||
movebits = bb_knight_moves(not_my_pieces, from);
|
||||
bit_for_each64(to, tmp2, movebits & empty) {
|
||||
moves[(*nmoves)++] = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp2, movebits & enemy_pieces) {
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
from_bb = pos->bb[us][KNIGHT];
|
||||
while (from_bb) {
|
||||
from = bb_next(&from_bb);
|
||||
to_bb = bb_knight_moves(dest_squares, from);
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,91 +363,85 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist)
|
||||
bitboard_t rel_rank8 = bb_rel_rank(RANK_8, us);
|
||||
bitboard_t rel_rank3 = bb_rel_rank(RANK_3, us);
|
||||
|
||||
/* pawn: ranks 2-6 push 1 and 2 squares */
|
||||
movebits = pawn_shift_up(pos->bb[us][PAWN], us) & empty;
|
||||
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||
from = pawn_push_up(to, them); /* reverse push */
|
||||
moves[(*nmoves)++] = move_make(from, to);
|
||||
/* pawn: push */
|
||||
int shift = sq_up(us);
|
||||
tmp_bb = bb_shift(pos->bb[us][PAWN], shift) & empty;
|
||||
|
||||
to_bb = tmp_bb & ~rel_rank8 & dest_squares; /* non promotion */
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp1, movebits & rel_rank8) { /* promotions */
|
||||
from = pawn_push_up(to, them); /* reverse push */
|
||||
moves[(*nmoves)++] = move_make_promote(from, to, QUEEN);
|
||||
moves[(*nmoves)++] = move_make_promote(from, to, ROOK);
|
||||
moves[(*nmoves)++] = move_make_promote(from, to, BISHOP);
|
||||
moves[(*nmoves)++] = move_make_promote(from, to, KNIGHT);
|
||||
to_bb = tmp_bb & rel_rank8 & dest_squares; /* promotions */
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
moves = move_make_promotions(moves, from, to);
|
||||
}
|
||||
|
||||
/* possible second push */
|
||||
movebits = pawn_shift_up(movebits & rel_rank3, us) & empty;
|
||||
bit_for_each64(to, tmp1, movebits) {
|
||||
from = pawn_push_up(pawn_push_up(to, them), them);
|
||||
moves[(*nmoves)++] = move_make_flags(from, to, M_DPUSH);
|
||||
to_bb = bb_shift(tmp_bb & rel_rank3, shift) & empty & dest_squares;
|
||||
while(to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift - shift;
|
||||
*moves++ = move_make_flags(from, to, M_DPUSH);
|
||||
}
|
||||
|
||||
/* pawn: captures left */
|
||||
movebits = pawn_shift_upleft(pos->bb[us][PAWN], us) & enemy_pieces;
|
||||
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||
from = pawn_push_upleft(to, them); /* reverse capture */
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
bitboard_t filter = ~bb_rel_file(FILE_A, us);
|
||||
shift = sq_upleft(us);
|
||||
tmp_bb = bb_shift(pos->bb[us][PAWN] & filter, shift) & enemy_pieces;
|
||||
|
||||
to_bb = tmp_bb & ~rel_rank8;
|
||||
while (to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp1, movebits & rel_rank8) {
|
||||
from = pawn_push_upleft(to, them); /* reverse capture */
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
||||
to_bb = tmp_bb & rel_rank8;
|
||||
while (to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
moves = move_make_promotions(moves, from, to);
|
||||
}
|
||||
|
||||
/* pawn: captures right */
|
||||
movebits = pawn_shift_upright(pos->bb[us][PAWN], us) & enemy_pieces;
|
||||
bit_for_each64(to, tmp1, movebits & ~rel_rank8) {
|
||||
from = pawn_push_upright(to, them); /* reverse capture */
|
||||
moves[(*nmoves)++] = move_make_capture(from, to);
|
||||
filter = ~bb_rel_file(FILE_H, us);
|
||||
shift = sq_upright(us);
|
||||
tmp_bb = bb_shift(pos->bb[us][PAWN] & filter, shift) & enemy_pieces;
|
||||
to_bb = tmp_bb & ~rel_rank8;
|
||||
while (to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
*moves++ = move_make(from, to);
|
||||
}
|
||||
bit_for_each64(to, tmp1, movebits & rel_rank8) {
|
||||
from = pawn_push_upright(to, them); /* reverse capture */
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, QUEEN);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, ROOK);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, BISHOP);
|
||||
moves[(*nmoves)++] = move_make_promote_capture(from, to, KNIGHT);
|
||||
to_bb = tmp_bb & rel_rank8;
|
||||
while (to_bb) {
|
||||
to = bb_next(&to_bb);
|
||||
from = to - shift;
|
||||
moves = move_make_promotions(moves, from, to);
|
||||
}
|
||||
|
||||
/* pawn: en-passant */
|
||||
if ((to = pos->en_passant) != SQUARE_NONE) {
|
||||
movebits = mask(to);
|
||||
from_pawns = pos->bb[us][PAWN]
|
||||
& (pawn_shift_upleft(movebits, them) | pawn_shift_upright(movebits, them));
|
||||
bit_for_each64(from, tmp1, from_pawns) {
|
||||
moves[(*nmoves)++] = move_make_enpassant(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
/* castle - Attention ! Castling flags are assumed correct
|
||||
/* pawn: en-passant
|
||||
* TODO: special case when in-check here ?
|
||||
*/
|
||||
if (!pos->checkers) {
|
||||
bitboard_t rel_rank1 = bb_rel_rank(RANK_1, us);
|
||||
from = pos->king[us];
|
||||
square_t from_square[2] = { E1, E8 }; /* verify king is on E1/E8 */
|
||||
bug_on(can_castle(pos->castle, us) && from != from_square[us]);
|
||||
/* For castle, we check the opponent attacks on squares between from and to.
|
||||
* To square attack check will be done in gen_is_legal.
|
||||
*/
|
||||
if (can_oo(pos->castle, us)) {
|
||||
bitboard_t occmask = rel_rank1 & (FILE_Fbb | FILE_Gbb);
|
||||
if (!(occ & occmask) &&
|
||||
!sq_attackers(pos, occ, from+1, them)) { /* f1/f8 */
|
||||
moves[(*nmoves)++] = move_make_flags(from, from + 2, M_CASTLE_K);
|
||||
}
|
||||
}
|
||||
if (can_ooo(pos->castle, us)) {
|
||||
bitboard_t occmask = rel_rank1 & (FILE_Bbb | FILE_Cbb | FILE_Dbb);
|
||||
if (!(occ & occmask) &&
|
||||
!sq_attackers(pos, occ, from-1, them)) { /* d1/d8 */
|
||||
moves[(*nmoves)++] = move_make_flags(from, from - 2, M_CASTLE_Q);
|
||||
}
|
||||
}
|
||||
if ((to = pos->en_passant) != SQUARE_NONE) {
|
||||
to_bb = mask(to);
|
||||
/* if e.p not on file H, we may add an e.p move to "up-left" */
|
||||
filter = ~bb_rel_file(FILE_A, us);
|
||||
shift = sq_upleft(us);
|
||||
if (bb_shift(pos->bb[us][PAWN] & filter, shift) & to_bb)
|
||||
*moves++ = move_make_enpassant(to - shift, to);
|
||||
|
||||
filter = ~bb_rel_file(FILE_H, us);
|
||||
shift = sq_upright(us);
|
||||
if (bb_shift(pos->bb[us][PAWN] & filter, shift) & to_bb)
|
||||
*moves++ = move_make_enpassant(to - shift, to);
|
||||
}
|
||||
|
||||
/* TODO: add function per piece, and type, for easier debug
|
||||
*/
|
||||
return *nmoves;
|
||||
finish:
|
||||
return movelist->nmoves = moves - movelist->move;
|
||||
}
|
||||
|
Reference in New Issue
Block a user