diff --git a/src/chessdefs.h b/src/chessdefs.h index 2fb76ec..27bcdb5 100644 --- a/src/chessdefs.h +++ b/src/chessdefs.h @@ -57,20 +57,23 @@ typedef enum { CASTLE_W = (CASTLE_WK | CASTLE_WQ), /* 00000011 W castle mask */ CASTLE_B = (CASTLE_BK | CASTLE_BQ), /* 00001100 B castle mask */ - CASTLE_K = (1 << 0), /* generic K/Q, after doing : */ - CASTLE_Q = (1 << 1), /* flags >> (2 * color) */ + CASTLE_K = (1 << 0), /* generic K/Q, bits 0 and 1 */ + CASTLE_Q = (1 << 1), + CASTLE_KQ = (CASTLE_K |CASTLE_Q) } castle_rights_t; /* determine is oo or ooo is possible with castle flags f and color c */ -#define NORM_CASTLE(f, c) ((f) >> (2 * (c))) /* shift flags to bits 0/1 */ -#define CAN_OO(f, c) (NORM_CASTLE(f, c) & CASTLE_K) -#define CAN_OOO(f, c) (NORM_CASTLE(f, c) & CASTLE_Q) -#define CAN_CASTLE(f, c) (CAN_OO(f, c) | CAN_OOO(f, c)) +//#define NORM_CASTLE(f, c) ((f) >> (2 * (c))) /* shift flags to bits 0/1 */ +//#define +//(NORM_CASTLE(f, c) & CASTLE_Q) +#define can_oo(f, c) ((f) & (CASTLE_K << ((c) * 2))) +#define can_ooo(f, c) ((f) & (CASTLE_Q << ((c) * 2))) +#define can_castle(f, c) ((f) & (CASTLE_KQ << ((c) * 2))) -#define CLR_OO(f, c) (f & ~(CASTLE_K << (2 * (c)))) -#define CLR_OOO(f, c) (f & ~(CASTLE_Q << (2 * (c)))) -#define CLR_OO_OOO(f, c) (f & ~((CASTLE_K | CASTLE_Q) << (2 * (c)) )) +#define clr_oo(f, c) ((f) & ~(CASTLE_K << (2 * (c)))) +#define clr_ooo(f, c) ((f) & ~(CASTLE_Q << (2 * (c)))) +#define clr_castle(f, c) ((f) & ~(CASTLE_KQ << (2 * (c)) )) /* game phases */ diff --git a/src/move-do.c b/src/move-do.c index 3bd478b..e8d7478 100644 --- a/src/move-do.c +++ b/src/move-do.c @@ -25,10 +25,10 @@ /** * move_do() - do move. * @pos: &pos_t position - * @pmove: &move to apply + * @move: move to apply * @state: &state_t address where irreversible changes will be saved * - * @pmove is applied to @pos: + * @move is applied to @pos: * - bitboards and board are updated * - counters are updated: * - move count @@ -36,188 +36,137 @@ * - flags are possibly updated: * - castling * - en-passant - * @pmove is also modified in case of capture, to keep information about the - * grabbed piece. + * - captured piece (excl. en-passant) * * @return: pos. */ -pos_t *move_do(pos_t *pos, move_t *pmove, state_t *state) +pos_t *move_do(pos_t *pos, move_t move, state_t *state) { -# ifdef DEBUG_MOVE - //log(1, "new move: "); - //move_print(0, move, M_PR_NL | M_PR_LONG); -# endif - move_t move = *pmove; +//# ifdef DEBUG_MOVE_DO +// move_print(move, M_PR_NL | M_PR_LONG); +//# endif *state = pos->state; /* save irreversible changes */ 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 piece = PIECE(move->piece), newpiece = piece, captured = move->capture; - //int color = COLOR(move->piece); - //u64 bb_from = SQ88_2_BB(from), bb_to = SQ88_2_BB(to); + piece_t new_piece = piece; ++pos->clock_50; ++pos->plycount; + pos->en_passant = SQUARE_NONE; + pos->turn = them; + + if (is_promotion(move)) + new_piece = MAKE_PIECE(move_promoted(move), us); if (is_capture(move)) { - piece_t captured = pos->board[to]; - /* clear grabbed piece */ - if (!is_enpassant(move)) { - pos_clr_sq(pos, to); - *pmove = move_set_captured(move, PIECE(captured)); - } else { /* special ep case */ - file_t ep_file = sq_file(pos->en_passant); - square_t grabbed = sq_make(ep_file, sq_rel_rank(RANK_5, us)); - pos_clr_sq(pos, grabbed); - } pos->clock_50 = 0; + pos->captured = pos->board[to]; /* save capture info */ + pos_clr_sq(pos, to); /* clear square */ } else if (is_castle(move)) { /* handle rook move */ square_t rookfrom, rookto; if (is_castle_K(move)) { - rookfrom = sq_make(FILE_H, sq_rel_rank(RANK_1, us)); - rookto = to - 1; + rookfrom = sq_rel(H1, us); + rookto = sq_rel(F1, us); } else { - rookfrom = sq_make(FILE_A, sq_rel_rank(RANK_1, us)); - rookto = to + 1; + rookfrom = sq_rel(A1, us); + rookto = sq_rel(D1, us); } pos_set_sq(pos, rookto, pos->board[rookfrom]); pos_clr_sq(pos, rookfrom); - pos->castle = CLR_OO_OOO(pos->castle, us); - } else if (is_dpush(move)) { /* if pawn double push, set e.p. */ - square_t ep = sq_make(sq_file(from), sq_rel_rank(RANK_3, us)); - pos->en_passant = ep; - } else if (is_promotion(move)) { - - } - - CAN_CASTLE(pos->castle, us)) { /* check for castling rights */ - if (from == sq_rel(E1, us)) { /* king moved */ - pos->castle = CLR_OO_OOO(pos->castle, us); - } else - - } - switch (PIECE(piece)) { - case PAWN: - if (sq_rank(from) == sq_rel_rank(RANK_2, us) && - sq_rank(to) == sq_rel_rank(RANK_4, us)) { /* 2 squares push */ - square_t ep = sq_make(sq_file(from)) from + 8; - } - case KING: - + pos->castle = clr_castle(pos->castle, us); + } else if (PIECE(piece) == 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); + else if (is_enpassant(move)) { /* clear grabbed pawn */ + square_t grabbed = pawn_push_up(to, them); + pos_clr_sq(pos, grabbed); } } - /* move piece itself */ - pos_set_sq(pos, to, piece); - pos_clr_sq(pos, from); + pos_clr_sq(pos, from); /* always clear "from" and set "to" */ + pos_set_sq(pos, to, new_piece); - u64 bb_ep_grab = SQ88_2_BB(ep_grab); - - log_f(5, "en-passant=%d,%d\n", ep_file, color == WHITE ? 4 : 3); - piece_del(&new->board[ep_grab].s_piece->list); - new->board[ep_grab].piece = 0; - new->occupied[OPPONENT(color)] &= ~bb_ep_grab; - new->bb[OPPONENT(color)][BB_PAWN] &= ~bb_ep_grab; - - } else { - piece_del(&new->board[to].s_piece->list); - new->board[to].piece = 0; - new->occupied[OPPONENT(color)] &= ~bb_to; - new->bb[OPPONENT(color)][PIECETOBB(captured)] &= ~bb_to; - } - - } else if (move->flags & M_CASTLE_Q) { - uchar row = R88(from); - square_t rook_from = SQ88(0, row); - square_t rook_to = SQ88(3, row); - u64 bb_rook_from = SQ88_2_BB(rook_from); - u64 bb_rook_to = SQ88_2_BB(rook_to); - - new->board[rook_to] = new->board[rook_from]; - new->board[rook_to].s_piece->square = rook_to; - new->occupied[color] &= ~bb_rook_from; - new->occupied[color] |= bb_rook_to; - new->bb[color][PIECETOBB(BB_ROOK)] &= ~bb_rook_from; - new->bb[color][PIECETOBB(BB_ROOK)] |= bb_rook_to; - new->board[rook_from].piece = 0; - new->board[rook_from].s_piece = NULL; - //new->castle &= color == WHITE? ~CASTLE_W: ~CASTLE_B; - - } else if (move->flags & M_CASTLE_K) { - uchar row = R88(from); - square_t rook_from = SQ88(7, row); - square_t rook_to = SQ88(5, row); - u64 bb_rook_from = SQ88_2_BB(rook_from); - u64 bb_rook_to = SQ88_2_BB(rook_to); - - new->board[rook_to] = new->board[rook_from]; - new->board[rook_to].s_piece->square = rook_to; - new->occupied[color] &= ~bb_rook_from; - new->occupied[color] |= bb_rook_to; - new->bb[color][PIECETOBB(BB_ROOK)] &= ~bb_rook_from; - new->bb[color][PIECETOBB(BB_ROOK)] |= bb_rook_to; - new->board[rook_from].piece = 0; - new->board[rook_from].s_piece = NULL; - // new->castle &= color == WHITE? ~CASTLE_W: ~CASTLE_B; + /* update castling flags + * As we always consider flags are valid, we : + * - adjust our flags if relative from is "E1", "A1", H1" + * - adjust opp flags if relative to if "A8", H8" + */ + if (can_castle(pos->castle, us)) { /* do we save time with this test ? */ + square_t rel_e1 = sq_rel(E1, us); + square_t rel_a1 = sq_rel(A1, us); square_t rel_h1 = sq_rel(H1, us); + if (from == rel_e1) + pos->castle = clr_castle(pos->castle, us); + else if (from == rel_a1) + pos->castle = clr_ooo(pos->castle, us); + else if (from == rel_h1) + pos->castle = clr_oo(pos->castle, us); + } + if (can_castle(pos->castle, them)) { /* do we save time with this test ? */ + square_t rel_a8 = sq_rel(A8, us); square_t rel_h8 = sq_rel(H8, us); + if (to == rel_a8) + pos->castle = clr_ooo(pos->castle, them); + else if (to == rel_h8) + pos->castle = clr_oo(pos->castle, them); } - new->board[to] = new->board[from]; - /* fix dest square */ - new->board[to].s_piece->square = to; - if (move->flags & M_PROMOTION) { - log_f(5, "promotion to %s\n", P_SYM(move->promotion)); - log_f(5, "newpiece=%#x p=%#x\n", move->promotion, PIECE(move->promotion)); - newpiece = PIECE(move->promotion); - new->board[to].piece = move->promotion; - new->board[to].s_piece->piece = move->promotion; - } - /* replace old occupied bitboard by new one */ - new->occupied[color] &= ~bb_from; - new->occupied[color] |= bb_to; - new->bb[color][PIECETOBB(piece)] &= ~bb_from; - new->bb[color][PIECETOBB(newpiece)] |= bb_to; - if (move->flags & M_PROMOTION) { - log_f(5, "promotion color=%d bbpiece=%d\n", color, PIECETOBB(newpiece)); - //bitboard_print(new->bb[color][PIECETOBB(newpiece)]); - } - /* set en_passant */ - new->en_passant = 0; - if (piece == PAWN) { - if (R88(from) == 1 && R88(to) == 3) - pos->en_passant = SQ88(F88(from), 2); - else if (R88(from) == 6 && R88(to) == 4) - pos->en_passant = SQ88(F88(from), 5); - } - - /* always make "from" square empty */ - new->board[from].piece = 0; - new->board[from].s_piece = NULL; - - //printf("old turn=%d ", color); - //printf("new turn=%d\n", new->turn); - //fflush(stdout); - /* adjust castling flags */ - if ((bb_from | bb_to) & E1bb) - new->castle &= ~(CASTLE_WQ | CASTLE_WK); - else if ((bb_from | bb_to) & A1bb) - new->castle &= ~CASTLE_WQ; - else if ((bb_from | bb_to) & H1bb) - new->castle &= ~CASTLE_WK; - - if ((bb_from | bb_to) & E8bb) - new->castle &= ~(CASTLE_BQ | CASTLE_BK); - else if ((bb_from | bb_to) & A8bb) - new->castle &= ~CASTLE_BQ; - else if ((bb_from | bb_to) & H8bb) - new->castle &= ~CASTLE_BK; - - SET_COLOR(new->turn, OPPONENT(color)); /* pos color */ - return new; + return pos; } -void move_undo(pos_t *pos, __unused move_t move) +/** + * move_undo() - undo move. + * @pos: &pos_t position + * @move: move to undo + * @state: &state_t address where irreversible changes were saved + * + * @move is applied to @pos: + * - bitboards and board are updated + * - previous information is restored: + * - castling + * - en-passant + * - captured piece (excl. en-passant) + * - move count + * - 50-moves rule count + * + * @return: pos. + */ +pos_t *move_undo(pos_t *pos, const move_t move, const state_t *state) { - pos_del(pos); +//# ifdef DEBUG_MOVE + //log(1, "new move: "); + //move_print(0, move, M_PR_NL | M_PR_LONG); +//# endif + color_t them = pos->turn, us = OPPONENT(them); + square_t from = move_from(move), to = move_to(move); + piece_t piece = pos->board[to]; + + pos->state = *state; /* restore irreversible changes */ + + 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); + + if (is_capture(move)) { + pos_set_sq(pos, to, pos->captured); /* restore captured piece */ + } else if (is_castle(move)) { /* make reverse rook move */ + square_t rookfrom, rookto; + if (is_castle_K(move)) { + rookfrom = sq_rel(F1, us); + rookto = sq_rel(H1, us); + } else { + rookfrom = sq_rel(D1, us); + rookto = sq_rel(A1, us); + } + pos_set_sq(pos, rookto, pos->board[rookfrom]); + pos_clr_sq(pos, rookfrom); + } else if (is_enpassant(move)) { /* restore grabbed pawn */ + square_t grabbed = pawn_push_up(to, them); + pos_set_sq(pos, grabbed, MAKE_PIECE(PAWN, them)); + } + + return pos; }