diff --git a/src/move-gen.c b/src/move-gen.c index f410ce2..e22dd64 100644 --- a/src/move-gen.c +++ b/src/move-gen.c @@ -34,7 +34,7 @@ * * @return: true if move is valid, false otherwise. */ -bool pseudo_is_legal(pos_t *pos, move_t move) +bool pseudo_is_legal(const pos_t *pos, const move_t move) { color_t us = pos->turn, them = OPPONENT(us); square_t from = move_from(move), to = move_to(move), king = pos->king[us], sq; @@ -79,7 +79,7 @@ bool pseudo_is_legal(pos_t *pos, move_t move) * 5th relative rank. To do so, we create an occupation bb without * the 2 pawns. */ - if (move & M_CAPTURE && PIECE(pos->board[to]) == EMPTY) { + if (IS_CAPTURE(move) && PIECE(pos->board[to]) == EMPTY) { /* from rank bitboard */ bitboard_t rank5 = bb_sqrank[from]; /* enemy rooks/queens on from rank */ @@ -100,6 +100,51 @@ bool pseudo_is_legal(pos_t *pos, move_t move) return true; } +/** + * pos_next_legal() - get next legal move in position. + * @pos: position + * @start: &int, starting position in move list + * + * Get next valid move in @pos move list, from move @start, or MOVE_NONE. + * @start is set to next non-checked move in pseudo-legal list. + * Position pseudo-legal moves must be already calculated before calling this function. + * + * @return: move, or -1 if no move. + */ +move_t pos_next_legal(const pos_t *pos, int *start) +{ + int nmoves = pos->moves.nmoves; + const move_t *moves = pos->moves.move; + + while (*start < nmoves) { + move_t move = moves[*start]; + ++*start; + if (pseudo_is_legal(pos, move)) + return move; + } + return MOVE_NONE; +} + +/** + * pos_all_legal() - get the list of legal moves from pseudo-legal. + * @pos: position + * @dest: destination &movelist_t + * + * The pseudo-legal moves must be already calculated before calling this function. + * + * @Return: @dest + */ +movelist_t *pos_all_legal(const pos_t *pos, movelist_t *dest) +{ + dest->nmoves = 0; + move_t move; + int tmp = 0; + + while ((move = pos_next_legal(pos, &tmp)) != MOVE_NONE) + dest->move[dest->nmoves++] = move; + return dest; +} + /** * pos_gen_pseudomoves() - generate position pseudo-legal moves * @pos: position @@ -290,24 +335,3 @@ int pos_gen_pseudomoves(pos_t *pos) */ return (pos->moves.nmoves = nmoves); } - -/** - * pos_legalmoves() - generate position legal moves from pseudo-legal ones. - * @pos: position - * @dest: address where to store legal moves - * - * The pseudo-legal moves must be already calculated before calling this function. - * - * @Return: @dest - */ -movelist_t *pos_legalmoves(pos_t *pos, movelist_t *dest) -{ - int pseudo; - movelist_t *src = &pos->moves; - dest->nmoves = 0; - for (pseudo = 0; pseudo < src->nmoves; ++pseudo) { - if (pseudo_is_legal(pos, src->move[pseudo])) - dest->move[dest->nmoves++] = src->move[pseudo]; - } - return dest; -} diff --git a/src/move-gen.h b/src/move-gen.h index 51e5d55..a249c46 100644 --- a/src/move-gen.h +++ b/src/move-gen.h @@ -21,8 +21,9 @@ #include "piece.h" #include "move.h" -extern bool pseudo_is_legal(pos_t *pos, move_t move); -extern int pos_gen_pseudomoves(pos_t *pos); -extern movelist_t *pos_legalmoves(pos_t *pos, movelist_t *dest); +bool pseudo_is_legal(const pos_t *pos, const move_t move); +move_t pos_next_legal(const pos_t *pos, int *start); +movelist_t *pos_all_legal(const pos_t *pos, movelist_t *dest); +int pos_gen_pseudomoves(pos_t *pos); #endif /* MOVEGEN_H */ diff --git a/src/move.c b/src/move.c index 163f735..ace5ab6 100644 --- a/src/move.c +++ b/src/move.c @@ -107,11 +107,11 @@ char *move_str(char *dst, const move_t move, __unused const int flags) square_t from = move_from(move); square_t to = move_to(move); int len; - sprintf(dst, "%s-%s%n", sq_to_string(from), sq_to_string(to), &len); + sprintf(dst, "%s%s%n", sq_to_string(from), sq_to_string(to), &len); - if (move & M_PROMOTION) { + if (IS_PROMOTION(move)) { piece_t promoted = move_promoted(move); - sprintf(dst + len, "=%s", piece_to_low(promoted)); + sprintf(dst + len, "%s", piece_to_low(promoted)); } return dst; } @@ -127,7 +127,7 @@ char *move_str(char *dst, const move_t move, __unused const int flags) * M_PR_NCAPT: print move if non capture * M_PR_NUM: print also move number * M_PR_LONG: print long notation - * M_PR_NL: print a newline after move + * M_PR_NL: print a newline after each move * M_PR_EVAL: print move eval */ void moves_print(movelist_t *moves, __unused int flags) diff --git a/src/move.h b/src/move.h index 39749cc..8f38561 100644 --- a/src/move.h +++ b/src/move.h @@ -19,29 +19,52 @@ #include "board.h" /* move structure: - * 3 2 2 1 1 1 1 1 1 - * 1 5 3 8 7 5 4 2 1 6 5 0 - * UUUUUUUU FFFFFF ccc ppp tttttt ffffff + * 3 3 2 2 1 1 1 1 1 1 + * 1 0 5 3 8 7 5 4 2 1 6 5 0 + * S UUUUUUU FFFFFF ccc ppp tttttt ffffff * - * 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 - * ppp 3 15-17 piece_type_t 38000 (>>15)&7 promoted - * ccc 3 12-14 piece_type_t 7000 (>>12)&7 captured - * FFFFFF 6 18-23 move_flags_t fc0000 N/A flags - * UUUUUUUU 8 24-31 unused fe000000 N/A future usage ? + * bits len off range type mask get desc + * ffffff 6 0 0-5 square_t 077 &63 from + * tttttt 6 6 6-11 square_t 07700 (>>6)&63 to + * ppp 3 12 12-14 piece_type_t 070000 (>>12)&7 promoted + * ccc 3 15 15-17 piece_type_t 0700000 (>>15)&7 captured + * FFFFFF 6 18 18-23 move_flags_t 077000000 (>>18)&63 N/A flags + * UUUUUUU 7 24 24-30 unused 017700000000 future usage + * S 1 31 31-31 - 020000000000 sign */ -typedef u32 move_t; +typedef s32 move_t; + +/* special move_t values */ +#define MOVE_NONE (-1) +#define MOVE_NULL (0) /* hack: from = to = A1 */ + +enum { + M_OFF_FROM = 0, + M_OFF_TO = 6, + M_OFF_PROM = 12, + M_OFF_CAPT = 15, + M_OFF_FLAGS = 18 +}; 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; + //M_INVALID = -1, + //M_START = 18, + M_CAPTURE = mask(0), + M_ENPASSANT = mask(1), + M_PROMOTION = mask(2), + M_CASTLE_K = mask(3), /* maybe only one ? */ + M_CASTLE_Q = mask(5), /* maybe only one ? */ + M_CHECK = mask(6) /* maybe unknown/useless ? */ +} move_flags_t; + +#define MOVE_FLAGS(m) ((m) >> M_OFF_FLAGS) +#define IS_CAPTURE(m) (MOVE_FLAGS(m) & M_CAPTURE) +#define IS_ENPASSANT(m) (MOVE_FLAGS(m) & M_ENPASSANT) +#define IS_PROMOTION(m) (MOVE_FLAGS(m) & M_PROMOTION) +#define IS_CASTLE(m) (MOVE_FLAGS(m) & (M_CASTLE_K | M_CASTLE_Q)) +#define IS_CASTLE_K(m) (MOVE_FLAGS(m) & M_CASTLE_K) +#define IS_CASTLE_Q(m) (MOVE_FLAGS(m) & M_CASTLE_Q) +#define IS_CHECK(m) (MOVE_FLAGS(m) & M_CHECK) #define MOVES_MAX 256 @@ -58,27 +81,27 @@ static inline square_t move_from(move_t move) static inline square_t move_to(move_t move) { - return (move >> 6) & 077; + return (move >> M_OFF_TO) & 077; } static inline piece_t move_promoted(move_t move) { - return (move >> 12) & 07; + return (move >> M_OFF_PROM) & 07; } static inline piece_type_t move_captured(move_t move) { - return (move >> 15) & 07; + return (move >> M_OFF_CAPT) & 07; } static inline move_t move_make(square_t from, square_t to) { - return (to << 6) | from; + return (to << M_OFF_TO) | from; } -static inline move_t move_make_flags(square_t from, square_t to, move_type_t flags) +static inline move_t move_make_flags(square_t from, square_t to, move_flags_t flags) { - return move_make(from, to) | flags; + return move_make(from, to) | (flags << M_OFF_FLAGS); } static inline move_t move_make_capture(square_t from, square_t to) @@ -89,13 +112,13 @@ static inline move_t move_make_capture(square_t from, square_t to) 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 << 12); + return move_make_flags(from, to, M_PROMOTION) | (promoted << M_OFF_PROM); } 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 << 12); + return move_make_flags(from, to, M_CAPTURE | M_PROMOTION) | (promoted << M_OFF_PROM); } /* moves_print flags @@ -109,9 +132,6 @@ static inline move_t move_make_promote_capture(square_t from, square_t to, #define M_PR_SEPARATE 0x40 /* separate captures */ #define M_PR_LONG 0x80 -//pool_t *moves_pool_init(); -//void moves_pool_stats(); - //int move_print(int movenum, move_t *move, move_flags_t flags); char *move_str(char *dst, const move_t move, __unused const int flags); void moves_print(movelist_t *moves, int flags); diff --git a/test/movegen-test.c b/test/movegen-test.c index 03b31f1..9bc54c4 100644 --- a/test/movegen-test.c +++ b/test/movegen-test.c @@ -237,7 +237,7 @@ int main(int __unused ac, __unused char**av) /* print movelists */ send_stockfish_fen(outfd, fishpos, fen); pos_gen_pseudomoves(pos); - pos_legalmoves(pos, &legal); + pos_all_legal(pos, &legal); //printf("Fu "); //moves_print(fishpos, 0); //fflush(stdout);