From bd88da013cd141d7abc0f1c5de19c297fa47aecf Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 12 Nov 2021 11:00:59 +0100 Subject: [PATCH] pos: added mobility. move_gen: hangle castling --- src/chessdefs.h | 4 ++ src/move.c | 131 ++++++++++++++++++++++++++++++++++-------------- src/move.h | 7 +-- src/piece.c | 25 ++++++++- src/position.c | 8 ++- src/position.h | 6 +-- 6 files changed, 135 insertions(+), 46 deletions(-) diff --git a/src/chessdefs.h b/src/chessdefs.h index dd038f6..9930a9e 100644 --- a/src/chessdefs.h +++ b/src/chessdefs.h @@ -31,6 +31,9 @@ enum { E_COLOR = 8 }; + +/* piece bitmask in piece_t + */ enum { EMPTY = 0, PAWN = 1 << (E_PAWN - 1), /* 0x01 00000001 */ @@ -43,6 +46,7 @@ enum { #define WHITE 0 /* 0x00 00000000 */ #define BLACK 1 /* 0x01 00000001 */ +#define OPPONENT(p) !(p) #define MASK_PIECE 0x3F /* 00111111 */ #define MASK_COLOR 0x80 /* 10000000 */ diff --git a/src/move.c b/src/move.c index 4c00144..22aa9c0 100644 --- a/src/move.c +++ b/src/move.c @@ -33,6 +33,18 @@ static struct vector { [KING] = { 8, 0, { -1, -16, 1, 16, -15, -17, 15, 17 }} }; +/* squares needed to be empty & not controlled by opponent for castle. + * For black castle, same values 7 rows higher (>> 7*8) + */ +static struct can_castle { + bitboard_t controlled[2]; + bitboard_t occupied[2]; +} castle_squares[2] = { + /* Queen side King side Queen side King side */ + { { C1|D1|E1, E1|F1|G1, }, { B1|C1|D1, F1|G1 } }, + { { C8|D8|E8, E8|F8|G8, }, { B8|C8|D8, F8|G8 } } +}; + pool_t *moves_pool_init() { if (!moves_pool) @@ -114,7 +126,7 @@ void moves_print(pos_t *pos, move_flags_t flags) } static move_t *move_add(pos_t *pos, piece_t piece, square_t from, - square_t to) + square_t to) { board_t *board = pos->board; move_t *move; @@ -152,7 +164,7 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from, /* TODO: return nmoves */ static move_t *move_pawn_add(pos_t *pos, piece_t piece, square_t from, - square_t to, unsigned char rank7) + square_t to, unsigned char rank7) { move_t *move; piece_t promote; @@ -176,7 +188,7 @@ static move_t *move_pawn_add(pos_t *pos, piece_t piece, square_t from, /* pawn moves. We do not test for valid destination square here, * assuming position is valid. Is that correct ? */ -int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) +int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece, bool doit) { piece_t piece = PIECE(ppiece->piece); unsigned char color = COLOR(ppiece->piece); @@ -202,7 +214,7 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) } # ifdef DEBUG_MOVE - log_f(4, "pos:%p turn:%s piece:%d [%s %s] dir:%d at %#04x[%c%c]\n", + log_f(3, "pos:%p turn:%s piece:%d [%s %s] dir:%d at %#04x[%c%c]\n", pos, IS_WHITE(pos->turn)? "white": "black", piece, @@ -221,7 +233,9 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) # ifdef DEBUG_MOVE log_i(4, "pushing pawn %#04x\n", square); # endif - if ((move = move_pawn_add(pos, piece | color, square, new, rank7))) + //log_f(4, "pawn move mobility\n"); + pos->mobility[vcolor]++; + if (doit && (move = move_pawn_add(pos, piece | color, square, new, rank7))) count++; /* push 2 squares */ if (move && RANK88(square) == rank2) { @@ -230,14 +244,16 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) # ifdef DEBUG_MOVE log_i(4, "pushing pawn %#04x 2 squares\n", square); # endif - if ((move = move_pawn_add(pos, piece | color, square, new, rank7))) + //log_f(2, "pawn move2 mobility\n"); + pos->mobility[vcolor]++; + if (doit && (move = move_pawn_add(pos, piece | color, square, new, rank7))) count++; } } } - /* en passant */ - if (pos->en_passant && RANK88(square) == rank5) { + /* en passant - not accounted for mobility. Correct ? */ + if (doit && pos->en_passant && RANK88(square) == rank5) { unsigned char ep_file = FILE88(pos->en_passant); unsigned char sq_file = FILE88(square); @@ -266,7 +282,10 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece) continue; pos->controlled[vcolor] |= (1ULL << BB(FILE88(new), RANK88(new))); if (board[new].piece && COLOR(board[new].piece) != color) { - if ((move = move_pawn_add(pos, piece | color, square, new, rank7))) + //log_f(2, "pawn capture mobility\n"); + pos->mobility[vcolor]++; + if (doit && + ((move = move_pawn_add(pos, piece | color, square, new, rank7)))) count++; } } @@ -280,46 +299,70 @@ int pseudo_moves_castle(pos_t *pos) unsigned char rank1, castle_K, castle_Q; move_t *move = NULL; unsigned short count=0; + struct can_castle *can_castle; + bitboard_t controlled; + bitboard_t occupied = pos->occupied[WHITE] | pos->occupied[BLACK]; + +# ifdef DEBUG_MOVE + log_f(2, "pos:%p turn:%s\n", + pos, + IS_WHITE(pos->turn)? "white": "black"); +# endif if (IS_WHITE(color)) { rank1 = 0; castle_K = pos->castle & CASTLE_WK; castle_Q = pos->castle & CASTLE_WQ; + can_castle = castle_squares+WHITE; + controlled = pos->controlled[BLACK]; } else { rank1 = 7; castle_K = pos->castle & CASTLE_BK; castle_Q = pos->castle & CASTLE_BQ; + can_castle = castle_squares+BLACK; + controlled = pos->controlled[WHITE]; + } + if (castle_K) { + if (occupied & can_castle->occupied[1]) { + printf("Cannot castle K side: occupied\n"); + goto next; + } + if (controlled & can_castle->controlled[1]) { + printf("Cannot castle K side: controlled\n"); + goto next; + } + move = move_add(pos, board[SQUARE(4, rank1)].piece, + SQUARE(4, rank1), SQUARE(6, rank1)); + if (move) { + move->flags |= M_CASTLE_K; + count++; + } } - if (castle_K) { - if (!(board[SQUARE(5, rank1)].piece || - board[SQUARE(6, rank1)].piece)) { - move = move_add(pos, board[SQUARE(4, rank1)].piece, - SQUARE(4, rank1), SQUARE(6, rank1)); - if (move) { - move->flags |= M_CASTLE_K; - } - count++; - } - } +next: if (castle_Q) { - if (!(board[SQUARE(1, rank1)].piece || - board[SQUARE(2, rank1)].piece || - board[SQUARE(3, rank1)].piece )) { - move = move_add(pos, board[SQUARE(4, rank1)].piece, - SQUARE(4, rank1), SQUARE(2, rank1)); - if (move) { - move->flags |= M_CASTLE_Q; - } + if (occupied & can_castle->occupied[0]) { + printf("Cannot castle Q side: occupied\n"); + goto end; + } + if (controlled & can_castle->controlled[0]) { + printf("Cannot castle Q side: controlled\n"); + goto end; + } + move = move_add(pos, board[SQUARE(4, rank1)].piece, + SQUARE(4, rank1), SQUARE(2, rank1)); + if (move) { + move->flags |= M_CASTLE_Q; count++; } } +end: return count; } /* general rule moves for non pawn pieces */ -int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece) +int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece, bool doit) { piece_t piece = PIECE(ppiece->piece); unsigned char color = COLOR(ppiece->piece); @@ -333,11 +376,12 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece) int count = 0; # ifdef DEBUG_MOVE - log_f(4, "pos:%p turn:%s piece:%d [%s %s] at %#04x[%c%c]\n", + log_f(1, "pos:%p turn:%s piece:%d [%s %s] at %#04x[%c%c]\n", pos, IS_WHITE(pos->turn)? "white": "black", piece, - IS_WHITE(color)? "white": "black", P_NAME(piece), + IS_WHITE(color)? "white": "black", + P_NAME(piece), square, FILE2C(GET_F(square)), RANK2C(GET_R(square))); log_i(5, "vector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide); @@ -372,7 +416,9 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece) } /* we are sure the move is valid : we create move */ - if (color == pos->turn) { + //log_f(2, "piece mobility\n"); + pos->mobility[vcolor]++; + if (doit && color == pos->turn) { if ((move = move_add(pos, ppiece->piece, square, new))) { count++; } @@ -387,21 +433,26 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece) return count; } -int moves_gen(pos_t *pos, bool color) +int moves_gen(pos_t *pos, bool color, bool doit) { struct list_head *p_cur, *tmp, *piece_list; piece_list_t *piece; int count = 0; +# ifdef DEBUG_MOVE + log_f(1, "color:%s doit:%d\n", color? "Black": "White", doit); +# endif piece_list = &pos->pieces[color]; - pseudo_moves_castle(pos); + pos->mobility[color]=0; + if (doit) + pseudo_moves_castle(pos); list_for_each_safe(p_cur, tmp, piece_list) { piece = list_entry(p_cur, piece_list_t, list); if (PIECE(piece->piece) != PAWN) - pseudo_moves_gen(pos, piece); + pseudo_moves_gen(pos, piece, doit); else - pseudo_moves_pawn(pos, piece); + pseudo_moves_pawn(pos, piece, doit); count++; } @@ -424,10 +475,14 @@ int main(int ac, char**av) } else { fen2pos(pos, av[1]); } - moves_gen(pos, WHITE); - moves_gen(pos, BLACK); + printf("turn = %d opponent = %d\n", pos->turn, OPPONENT(pos->turn)); + moves_gen(pos, OPPONENT(pos->turn), false); + moves_gen(pos, pos->turn, true); pos_print(pos); pos_pieces_print(pos); moves_print(pos, M_PR_SEPARATE); + + //bitboard_print2(castle_squares[0].controlled, castle_squares[1].controlled); + //bitboard_print2(castle_squares[0].occupied, castle_squares[1].occupied); } #endif diff --git a/src/move.h b/src/move.h index 346d2ef..7302cce 100644 --- a/src/move.h +++ b/src/move.h @@ -54,8 +54,9 @@ pool_t *moves_pool_init(); int move_print(move_t *move, move_flags_t flags); void moves_print(pos_t *move, move_flags_t flags); int pseudo_moves_castle(pos_t *pos); -int pseudo_moves_gen(pos_t *pos, piece_list_t *piece); -int pseudo_moves_pawn(pos_t *pos, piece_list_t *piece); -int moves_gen(pos_t *pos, bool color); + +int pseudo_moves_gen(pos_t *pos, piece_list_t *piece, bool doit); +int pseudo_moves_pawn(pos_t *pos, piece_list_t *piece, bool doit); +int moves_gen(pos_t *pos, bool color, bool doit); #endif /* MODE_H */ diff --git a/src/piece.c b/src/piece.c index 0b0e0f1..ce62524 100644 --- a/src/piece.c +++ b/src/piece.c @@ -66,7 +66,7 @@ piece_list_t *piece_add(pos_t *pos, piece_t piece, square_t square) short color = VCOLOR(piece); # ifdef DEBUG_PIECE - log_f(2, "piece=%02x square=%02x\n", piece, square); + log_f(3, "piece=%02x square=%02x\n", piece, square); log_f(5, "Adding %s %s on %c%c\n", color? "Black": "White", P_NAME(piece), FILE2C(GET_F(square)), RANK2C(GET_R(square))); # endif @@ -99,5 +99,28 @@ int main(int ac, char**av) } pos_print(pos); pos_pieces_print(pos); + printf("0x1c:\n"); + bitboard_print(0x1c); + printf("0x70:\n"); + bitboard_print(0x70); + printf("0x0e:\n"); + bitboard_print(0x0e); + printf("0x60:\n"); + bitboard_print(0x60); + + printf("A1:\n"); + bitboard_print(A1); + printf("1:\n"); + bitboard_print(1L); + printf("H1:\n"); + bitboard_print(H1); + printf("C1:\n"); + bitboard_print(C1); + printf("D1:\n"); + bitboard_print(D1); + printf("C1|D1:\n"); + bitboard_print(C1|D1); + printf("H8:\n"); + bitboard_print(H8); } #endif diff --git a/src/position.c b/src/position.c index 28124ac..ec4e037 100644 --- a/src/position.c +++ b/src/position.c @@ -36,7 +36,7 @@ inline void bitboard_print(bitboard_t bb) { int i; printf("%#018lx\n", bb); - for (i=56; i; i-=8) + for (i=56; i>=0; i-=8) printf("\t"BYTE_PRINT"\n", BYTE2BIN(bb>>i)); } @@ -108,6 +108,10 @@ void pos_print(pos_t *pos) printf("\n50 half-moves-rule = %d\n", pos->clock_50); printf("Current move = %d\n", pos->curmove); + printf("Squares controlled: W:%d B:%d\n", popcount64(pos->controlled[WHITE]), + popcount64(pos->controlled[BLACK])); + printf("Mobility: W:%u B:%u\n", pos->mobility[WHITE], + pos->mobility[BLACK]); printf("Bitbords occupied :\n"); bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]); printf("Bitbords controlled :\n"); @@ -141,6 +145,8 @@ pos_t *pos_init(pos_t *pos) pos->occupied[BLACK] = 0; pos->controlled[WHITE] = 0; pos->controlled[BLACK] = 0; + pos->mobility[WHITE] = 0; + pos->mobility[BLACK] = 0; INIT_LIST_HEAD(&pos->pieces[WHITE]); INIT_LIST_HEAD(&pos->pieces[BLACK]); INIT_LIST_HEAD(&pos->moves); diff --git a/src/position.h b/src/position.h index 8da725f..fd04249 100644 --- a/src/position.h +++ b/src/position.h @@ -22,8 +22,9 @@ typedef struct pos_s { piece_t turn; /* we use only color bit */ castle_t castle; - uint16_t clock_50; - uint16_t curmove; + u16 clock_50; + u16 curmove; + u16 mobility[2]; eval_t eval; board_t *board; @@ -31,7 +32,6 @@ typedef struct pos_s { square_t king[2]; bitboard_t occupied[2]; bitboard_t controlled[2]; - struct list_head pieces[2]; struct list_head moves; } pos_t;