diff --git a/src/move-gen.c b/src/move-gen.c index def592f..f98f8e5 100644 --- a/src/move-gen.c +++ b/src/move-gen.c @@ -27,18 +27,6 @@ #include "move-gen.h" -/** - * gen_castle() - generate c - * @pos: position - * - * Generate all pseudo pawn pushes. - */ -//int gen_pawn_push(pos_t *pos, bitboard_t occ) -//{ - - -//} - /** * pseudo_is_legal() - check if a move is legal. * @pos: position @@ -47,10 +35,11 @@ * We check all possible invalid moves: * (1) King: * - K moves to a controlled square - * - Castling: - * - K passes a controlled square - already done in pseudomove gen + * (1) Castling: + * - K passes a controlled square - already done in pseudomove gen * - * (2) En-passant: + * + * (3) En-passant: * - pinned taking pawn, done in (3) * - taking and taken pawn on same rank than king, discovered check on rank * @@ -103,10 +92,21 @@ bool pseudo_is_legal(pos_t *pos, move_t move) * gen_all_pseudomoves() - generate all pseudo moves * @pos: position * - * Generate all moves, no check is done on validity due to castle rules, - * or check (pinned pieces, etc...). + * Generate all @pos pseudo moves for player-to-move. + * The @pos->moves table is filled with the moves. * - * @return: The number of moves. + * Only a few validity checks are done here (i.e. moves are not generated): + * - castling, if king is in check + * - castling, if king passes an enemy-controlled square (not final square). + * When immediately known, a few move flags are also applied in these cases: + * - castling: M_CASTLE_{K,Q} + * - pawn capture (incl. en-passant): M_CAPTURE + * - promotion: M_PROMOTION + * - promotion and capture + * + * TODO: move code to specific functions (especially castling, pawn push/capture) + * + * @Return: The total number of moves. */ int gen_all_pseudomoves(pos_t *pos) { @@ -127,7 +127,7 @@ int gen_all_pseudomoves(pos_t *pos) int from, to; - /* king */ + /* king - MUST BE FIRST ! */ from = pos->king[us]; movebits = bb_king_moves(not_my_pieces, from); bit_for_each64(to, tmp2, movebits) { @@ -187,11 +187,28 @@ int gen_all_pseudomoves(pos_t *pos) //printf("push %d->%d %s->%s", from, to, sq_to_string(from), sq_to_string(to)); moves[nmoves++] = move_make(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(from, to); } + + /* pawn: ranks 2-6 captures left, including en-passant */ + from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_filea; + movebits = pawn_shift_upleft(from_pawns, us) & enemy_avail; + bit_for_each64(to, tmp1, movebits) { + from = pawn_push_upleft(to, them); /* reverse capture */ + moves[nmoves++] = move_make_capture(from, to); + } + /* pawn: ranks 2-6 captures right, including en-passant */ + from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_fileh; + movebits = pawn_shift_upright(from_pawns, us) & enemy_avail; + bit_for_each64(to, tmp1, movebits) { + from = pawn_push_upright(to, them); + moves[nmoves++] = move_make_capture(from, to); + } + /* pawn: rank 7 push */ movebits = pawn_shift_up(pos->bb[us][PAWN] & rel_rank7, us) & empty; bit_for_each64(to, tmp1, movebits) { @@ -201,44 +218,28 @@ int gen_all_pseudomoves(pos_t *pos) moves[nmoves++] = move_make_promote(from, to, BISHOP); moves[nmoves++] = move_make_promote(from, to, KNIGHT); } - - /* pawn: ranks 2-6 captures left, including en-passant */ - from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_filea; - movebits = pawn_shift_upleft(from_pawns, us) & enemy_avail; - bit_for_each64(to, tmp1, movebits) { - from = pawn_push_upleft(to, them); /* reverse capture */ - moves[nmoves++] = move_make(from, to); - } - /* pawn: rank 7 captures left */ + /* pawn promotion: rank 7 captures left */ from_pawns = pos->bb[us][PAWN] & rel_rank7; // & ~rel_filea; movebits = pawn_shift_upleft(from_pawns, us) & enemy_avail; bit_for_each64(to, tmp1, movebits) { from = pawn_push_upleft(to, them); /* reverse capture */ - 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); - } - - /* pawn: ranks 2-6 captures right, including en-passant */ - from_pawns = pos->bb[us][PAWN] & ~rel_rank7; // & ~rel_fileh; - movebits = pawn_shift_upright(from_pawns, us) & enemy_avail; - bit_for_each64(to, tmp1, movebits) { - from = pawn_push_upright(to, them); - moves[nmoves++] = move_make(from, to); + 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); } /* pawn: rank 7 captures right */ from_pawns = pos->bb[us][PAWN] & rel_rank7; // & ~rel_fileh; movebits = pawn_shift_upright(from_pawns, us) & enemy_pieces; bit_for_each64(to, tmp1, movebits) { from = pawn_push_upright(to, them); /* reverse capture */ - 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); + 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); } - /* castle - Attention ! We consider that castle flags are correct, + /* castle - Attention ! Castling flags are assumed correct */ if (!pos->checkers) { bitboard_t rel_rank1 = BB_REL_RANK(RANK_1, us); diff --git a/src/move.h b/src/move.h index 68e3a73..6292e15 100644 --- a/src/move.h +++ b/src/move.h @@ -19,50 +19,52 @@ #include "board.h" /* move structure: - * 3 2 2 1 1 1 1 1 1 - * 1 5 4 8 7 5 4 2 1 6 5 0 - * UUUUUUU FFFFFFF ppp ccc tttttt ffffff + * 3 2 2 1 1 1 1 1 1 + * 1 5 3 8 7 5 4 2 1 6 5 0 + * UUUUUUUU FFFFFF ppp ccc tttttt ffffff * - * bits range type mask get desc - * ffffff 0-5 square_t 3f &63 from - * tttttt 6-11 square_t fc0 (>>6)&63 to - * ccc 12-14 piece_type_t 7000 (>>12)&7 captured - * ppp 15-17 piece_type_t 38000 (>>15)&7 promoted - * FFFFFFF 18-24 N/A 1fc0000 N/A flags - * UUUUUUU 25-31 unused fe000000 N/A future usage ? + * bits len range type mask get desc + * ffffff 6 0-5 square_t 3f &63 from + * tttttt 6 6-11 square_t fc0 (>>6)&63 to + * ccc 3 12-14 piece_type_t 7000 (>>12)&7 captured + * ppp 3 15-17 piece_type_t 38000 (>>15)&7 promoted + * FFFFFF 6 18-23 move_flags_t fc0000 N/A flags + * UUUUUUUU 8 24-31 unused fe000000 N/A future usage ? */ -#define move_t u32 +typedef u32 move_t; -/* move flags */ -#define M_FLAGS_BEG 18 -#define M_HAS_FLAGS mask(M_FLAGS_BEG + 0) /* probably unused */ -#define M_CAPTURE mask(M_FLAGS_BEG + 1) -#define M_EPASSANT mask(M_FLAGS_BEG + 2) -#define M_PROMOTE mask(M_FLAGS_BEG + 3) -#define M_CASTLE_K mask(M_FLAGS_BEG + 4) -#define M_CASTLE_Q mask(M_FLAGS_BEG + 5) -#define M_CHECK mask(M_FLAGS_BEG + 6) /* probably unknown/useless */ - -#define M_FLAGS (M_CAPTURE | M_ENPASSANT | M_PROMOTION | \ - M_CASTLE_K | M_CASTLE_Q | M_CHECK) -#define M_NORMAL (~M_FLAGS) +typedef enum { + M_START = 18, + M_CAPTURE = (1 << (M_START + 0)), + M_ENPASSANT = (1 << (M_START + 1)), + M_PROMOTION = (1 << (M_START + 2)), + M_CASTLE_K = (1 << (M_START + 3)), /* maybe only one ? */ + M_CASTLE_Q = (1 << (M_START + 4)), /* maybe only one ? */ + M_CHECK = (1 << (M_START + 5)) /* maybe unknown/useless ? */ +} move_type_t; #define MOVES_MAX 256 -static inline move_t move_make(square_t from, square_t to) -{ - return (to << 6) | from; -} +typedef struct __movelist_s { + move_t move[MOVES_MAX]; + int nmoves; /* total moves (fill) */ + int curmove; /* current move (use) */ +} movelist_t; -static inline move_t move_make_flags(square_t from, square_t to, int flags) -{ - return move_make(from, to) | flags; -} -static inline move_t move_make_promote(square_t from, square_t to, piece_type_t piece) -{ - return move_make(from, to) | M_PROMOTE | (piece << 15); -} +/* move flags */ +//#define M_FLAGS_BEG 18 +//#define M_HAS_FLAGS mask(M_FLAGS_BEG + 0) /* probably useless */ +//#define M_CAPTURE mask(M_FLAGS_BEG + 0) +//#define M_EN_PASSANT mask(M_FLAGS_BEG + 1) +//#define M_PROMOTION mask(M_FLAGS_BEG + 2) +//#define M_CASTLE_K mask(M_FLAGS_BEG + 3) /* maybe only one ? */ +//#define M_CASTLE_Q mask(M_FLAGS_BEG + 4) /* maybe only one ? */ +//#define M_CHECK mask(M_FLAGS_BEG + 5) /* probably unknown/useless */ + +//#define M_FLAGS (M_CAPTURE | M_ENPASSANT | M_PROMOTION | +// M_CASTLE_K | M_CASTLE_Q | M_CHECK) +//#define M_NORMAL (~M_FLAGS) static inline square_t move_from(move_t move) { @@ -73,6 +75,43 @@ static inline square_t move_to(move_t move) return (move >> 6) & 077; } +static inline piece_t move_promoted(move_t move) +{ + return (move >> 15) & 07; +} + +static inline piece_t move_captured(move_t move) +{ + return (move >> 12) & 07; +} + +static inline move_t move_make(square_t from, square_t to) +{ + return (to << 6) | from; +} + +static inline move_t move_make_flags(square_t from, square_t to, move_type_t flags) +{ + return move_make(from, to) | flags; +} + +static inline move_t move_make_capture(square_t from, square_t to) +{ + return move_make_flags(from, to, M_CAPTURE); +} + +static inline move_t move_make_promote(square_t from, square_t to, + piece_type_t promoted) +{ + return move_make_flags(from, to, M_PROMOTION) | (promoted << 15); +} + +static inline move_t move_make_promote_capture(square_t from, square_t to, + piece_type_t promoted) +{ + return move_make_flags(from, to, M_CAPTURE | M_PROMOTION) | (promoted << 15); +} + /* moves_print flags */ #define M_PR_CAPT 0x01 @@ -83,12 +122,6 @@ static inline square_t move_to(move_t move) #define M_PR_SEPARATE 0x40 /* separate captures */ #define M_PR_LONG 0x80 -typedef struct __movelist_s { - move_t move[MOVES_MAX]; - int nmoves; /* total moves (fill) */ - int curmove; /* current move (use) */ -} movelist_t; - //pool_t *moves_pool_init(); //void moves_pool_stats();