pos: added mobility. move_gen: hangle castling
This commit is contained in:
@@ -31,6 +31,9 @@ enum {
|
|||||||
E_COLOR = 8
|
E_COLOR = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* piece bitmask in piece_t
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
EMPTY = 0,
|
EMPTY = 0,
|
||||||
PAWN = 1 << (E_PAWN - 1), /* 0x01 00000001 */
|
PAWN = 1 << (E_PAWN - 1), /* 0x01 00000001 */
|
||||||
@@ -43,6 +46,7 @@ enum {
|
|||||||
|
|
||||||
#define WHITE 0 /* 0x00 00000000 */
|
#define WHITE 0 /* 0x00 00000000 */
|
||||||
#define BLACK 1 /* 0x01 00000001 */
|
#define BLACK 1 /* 0x01 00000001 */
|
||||||
|
#define OPPONENT(p) !(p)
|
||||||
|
|
||||||
#define MASK_PIECE 0x3F /* 00111111 */
|
#define MASK_PIECE 0x3F /* 00111111 */
|
||||||
#define MASK_COLOR 0x80 /* 10000000 */
|
#define MASK_COLOR 0x80 /* 10000000 */
|
||||||
|
103
src/move.c
103
src/move.c
@@ -33,6 +33,18 @@ static struct vector {
|
|||||||
[KING] = { 8, 0, { -1, -16, 1, 16, -15, -17, 15, 17 }}
|
[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()
|
pool_t *moves_pool_init()
|
||||||
{
|
{
|
||||||
if (!moves_pool)
|
if (!moves_pool)
|
||||||
@@ -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,
|
/* pawn moves. We do not test for valid destination square here,
|
||||||
* assuming position is valid. Is that correct ?
|
* 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);
|
piece_t piece = PIECE(ppiece->piece);
|
||||||
unsigned char color = COLOR(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
|
# 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,
|
pos,
|
||||||
IS_WHITE(pos->turn)? "white": "black",
|
IS_WHITE(pos->turn)? "white": "black",
|
||||||
piece,
|
piece,
|
||||||
@@ -221,7 +233,9 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece)
|
|||||||
# ifdef DEBUG_MOVE
|
# ifdef DEBUG_MOVE
|
||||||
log_i(4, "pushing pawn %#04x\n", square);
|
log_i(4, "pushing pawn %#04x\n", square);
|
||||||
# endif
|
# 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++;
|
count++;
|
||||||
/* push 2 squares */
|
/* push 2 squares */
|
||||||
if (move && RANK88(square) == rank2) {
|
if (move && RANK88(square) == rank2) {
|
||||||
@@ -230,14 +244,16 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece)
|
|||||||
# ifdef DEBUG_MOVE
|
# ifdef DEBUG_MOVE
|
||||||
log_i(4, "pushing pawn %#04x 2 squares\n", square);
|
log_i(4, "pushing pawn %#04x 2 squares\n", square);
|
||||||
# endif
|
# 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++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* en passant */
|
/* en passant - not accounted for mobility. Correct ? */
|
||||||
if (pos->en_passant && RANK88(square) == rank5) {
|
if (doit && pos->en_passant && RANK88(square) == rank5) {
|
||||||
unsigned char ep_file = FILE88(pos->en_passant);
|
unsigned char ep_file = FILE88(pos->en_passant);
|
||||||
unsigned char sq_file = FILE88(square);
|
unsigned char sq_file = FILE88(square);
|
||||||
|
|
||||||
@@ -266,7 +282,10 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece)
|
|||||||
continue;
|
continue;
|
||||||
pos->controlled[vcolor] |= (1ULL << BB(FILE88(new), RANK88(new)));
|
pos->controlled[vcolor] |= (1ULL << BB(FILE88(new), RANK88(new)));
|
||||||
if (board[new].piece && COLOR(board[new].piece) != color) {
|
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++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,46 +299,70 @@ int pseudo_moves_castle(pos_t *pos)
|
|||||||
unsigned char rank1, castle_K, castle_Q;
|
unsigned char rank1, castle_K, castle_Q;
|
||||||
move_t *move = NULL;
|
move_t *move = NULL;
|
||||||
unsigned short count=0;
|
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)) {
|
if (IS_WHITE(color)) {
|
||||||
rank1 = 0;
|
rank1 = 0;
|
||||||
castle_K = pos->castle & CASTLE_WK;
|
castle_K = pos->castle & CASTLE_WK;
|
||||||
castle_Q = pos->castle & CASTLE_WQ;
|
castle_Q = pos->castle & CASTLE_WQ;
|
||||||
|
can_castle = castle_squares+WHITE;
|
||||||
|
controlled = pos->controlled[BLACK];
|
||||||
} else {
|
} else {
|
||||||
rank1 = 7;
|
rank1 = 7;
|
||||||
castle_K = pos->castle & CASTLE_BK;
|
castle_K = pos->castle & CASTLE_BK;
|
||||||
castle_Q = pos->castle & CASTLE_BQ;
|
castle_Q = pos->castle & CASTLE_BQ;
|
||||||
|
can_castle = castle_squares+BLACK;
|
||||||
|
controlled = pos->controlled[WHITE];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (castle_K) {
|
if (castle_K) {
|
||||||
if (!(board[SQUARE(5, rank1)].piece ||
|
if (occupied & can_castle->occupied[1]) {
|
||||||
board[SQUARE(6, rank1)].piece)) {
|
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,
|
move = move_add(pos, board[SQUARE(4, rank1)].piece,
|
||||||
SQUARE(4, rank1), SQUARE(6, rank1));
|
SQUARE(4, rank1), SQUARE(6, rank1));
|
||||||
if (move) {
|
if (move) {
|
||||||
move->flags |= M_CASTLE_K;
|
move->flags |= M_CASTLE_K;
|
||||||
}
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
if (castle_Q) {
|
if (castle_Q) {
|
||||||
if (!(board[SQUARE(1, rank1)].piece ||
|
if (occupied & can_castle->occupied[0]) {
|
||||||
board[SQUARE(2, rank1)].piece ||
|
printf("Cannot castle Q side: occupied\n");
|
||||||
board[SQUARE(3, rank1)].piece )) {
|
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,
|
move = move_add(pos, board[SQUARE(4, rank1)].piece,
|
||||||
SQUARE(4, rank1), SQUARE(2, rank1));
|
SQUARE(4, rank1), SQUARE(2, rank1));
|
||||||
if (move) {
|
if (move) {
|
||||||
move->flags |= M_CASTLE_Q;
|
move->flags |= M_CASTLE_Q;
|
||||||
}
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* general rule moves for non pawn pieces
|
/* 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);
|
piece_t piece = PIECE(ppiece->piece);
|
||||||
unsigned char color = COLOR(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;
|
int count = 0;
|
||||||
|
|
||||||
# ifdef DEBUG_MOVE
|
# 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,
|
pos,
|
||||||
IS_WHITE(pos->turn)? "white": "black",
|
IS_WHITE(pos->turn)? "white": "black",
|
||||||
piece,
|
piece,
|
||||||
IS_WHITE(color)? "white": "black", P_NAME(piece),
|
IS_WHITE(color)? "white": "black",
|
||||||
|
P_NAME(piece),
|
||||||
square,
|
square,
|
||||||
FILE2C(GET_F(square)), RANK2C(GET_R(square)));
|
FILE2C(GET_F(square)), RANK2C(GET_R(square)));
|
||||||
log_i(5, "vector=%ld ndirs=%d slide=%d\n", vector-vectors, ndirs, slide);
|
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 */
|
/* 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))) {
|
if ((move = move_add(pos, ppiece->piece, square, new))) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -387,21 +433,26 @@ int pseudo_moves_gen(pos_t *pos, piece_list_t *ppiece)
|
|||||||
return count;
|
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;
|
struct list_head *p_cur, *tmp, *piece_list;
|
||||||
piece_list_t *piece;
|
piece_list_t *piece;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
# ifdef DEBUG_MOVE
|
||||||
|
log_f(1, "color:%s doit:%d\n", color? "Black": "White", doit);
|
||||||
|
# endif
|
||||||
piece_list = &pos->pieces[color];
|
piece_list = &pos->pieces[color];
|
||||||
|
|
||||||
|
pos->mobility[color]=0;
|
||||||
|
if (doit)
|
||||||
pseudo_moves_castle(pos);
|
pseudo_moves_castle(pos);
|
||||||
list_for_each_safe(p_cur, tmp, piece_list) {
|
list_for_each_safe(p_cur, tmp, piece_list) {
|
||||||
piece = list_entry(p_cur, piece_list_t, list);
|
piece = list_entry(p_cur, piece_list_t, list);
|
||||||
if (PIECE(piece->piece) != PAWN)
|
if (PIECE(piece->piece) != PAWN)
|
||||||
pseudo_moves_gen(pos, piece);
|
pseudo_moves_gen(pos, piece, doit);
|
||||||
else
|
else
|
||||||
pseudo_moves_pawn(pos, piece);
|
pseudo_moves_pawn(pos, piece, doit);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -424,10 +475,14 @@ int main(int ac, char**av)
|
|||||||
} else {
|
} else {
|
||||||
fen2pos(pos, av[1]);
|
fen2pos(pos, av[1]);
|
||||||
}
|
}
|
||||||
moves_gen(pos, WHITE);
|
printf("turn = %d opponent = %d\n", pos->turn, OPPONENT(pos->turn));
|
||||||
moves_gen(pos, BLACK);
|
moves_gen(pos, OPPONENT(pos->turn), false);
|
||||||
|
moves_gen(pos, pos->turn, true);
|
||||||
pos_print(pos);
|
pos_print(pos);
|
||||||
pos_pieces_print(pos);
|
pos_pieces_print(pos);
|
||||||
moves_print(pos, M_PR_SEPARATE);
|
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
|
#endif
|
||||||
|
@@ -54,8 +54,9 @@ pool_t *moves_pool_init();
|
|||||||
int move_print(move_t *move, move_flags_t flags);
|
int move_print(move_t *move, move_flags_t flags);
|
||||||
void moves_print(pos_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_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 pseudo_moves_gen(pos_t *pos, piece_list_t *piece, bool doit);
|
||||||
int moves_gen(pos_t *pos, bool color);
|
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 */
|
#endif /* MODE_H */
|
||||||
|
25
src/piece.c
25
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);
|
short color = VCOLOR(piece);
|
||||||
|
|
||||||
# ifdef DEBUG_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",
|
log_f(5, "Adding %s %s on %c%c\n", color? "Black": "White",
|
||||||
P_NAME(piece), FILE2C(GET_F(square)), RANK2C(GET_R(square)));
|
P_NAME(piece), FILE2C(GET_F(square)), RANK2C(GET_R(square)));
|
||||||
# endif
|
# endif
|
||||||
@@ -99,5 +99,28 @@ int main(int ac, char**av)
|
|||||||
}
|
}
|
||||||
pos_print(pos);
|
pos_print(pos);
|
||||||
pos_pieces_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
|
#endif
|
||||||
|
@@ -36,7 +36,7 @@ inline void bitboard_print(bitboard_t bb)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
printf("%#018lx\n", bb);
|
printf("%#018lx\n", bb);
|
||||||
for (i=56; i; i-=8)
|
for (i=56; i>=0; i-=8)
|
||||||
printf("\t"BYTE_PRINT"\n",
|
printf("\t"BYTE_PRINT"\n",
|
||||||
BYTE2BIN(bb>>i));
|
BYTE2BIN(bb>>i));
|
||||||
}
|
}
|
||||||
@@ -108,6 +108,10 @@ void pos_print(pos_t *pos)
|
|||||||
|
|
||||||
printf("\n50 half-moves-rule = %d\n", pos->clock_50);
|
printf("\n50 half-moves-rule = %d\n", pos->clock_50);
|
||||||
printf("Current move = %d\n", pos->curmove);
|
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");
|
printf("Bitbords occupied :\n");
|
||||||
bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]);
|
bitboard_print2(pos->occupied[WHITE], pos->occupied[BLACK]);
|
||||||
printf("Bitbords controlled :\n");
|
printf("Bitbords controlled :\n");
|
||||||
@@ -141,6 +145,8 @@ pos_t *pos_init(pos_t *pos)
|
|||||||
pos->occupied[BLACK] = 0;
|
pos->occupied[BLACK] = 0;
|
||||||
pos->controlled[WHITE] = 0;
|
pos->controlled[WHITE] = 0;
|
||||||
pos->controlled[BLACK] = 0;
|
pos->controlled[BLACK] = 0;
|
||||||
|
pos->mobility[WHITE] = 0;
|
||||||
|
pos->mobility[BLACK] = 0;
|
||||||
INIT_LIST_HEAD(&pos->pieces[WHITE]);
|
INIT_LIST_HEAD(&pos->pieces[WHITE]);
|
||||||
INIT_LIST_HEAD(&pos->pieces[BLACK]);
|
INIT_LIST_HEAD(&pos->pieces[BLACK]);
|
||||||
INIT_LIST_HEAD(&pos->moves);
|
INIT_LIST_HEAD(&pos->moves);
|
||||||
|
@@ -22,8 +22,9 @@
|
|||||||
typedef struct pos_s {
|
typedef struct pos_s {
|
||||||
piece_t turn; /* we use only color bit */
|
piece_t turn; /* we use only color bit */
|
||||||
castle_t castle;
|
castle_t castle;
|
||||||
uint16_t clock_50;
|
u16 clock_50;
|
||||||
uint16_t curmove;
|
u16 curmove;
|
||||||
|
u16 mobility[2];
|
||||||
eval_t eval;
|
eval_t eval;
|
||||||
board_t *board;
|
board_t *board;
|
||||||
|
|
||||||
@@ -31,7 +32,6 @@ typedef struct pos_s {
|
|||||||
square_t king[2];
|
square_t king[2];
|
||||||
bitboard_t occupied[2];
|
bitboard_t occupied[2];
|
||||||
bitboard_t controlled[2];
|
bitboard_t controlled[2];
|
||||||
|
|
||||||
struct list_head pieces[2];
|
struct list_head pieces[2];
|
||||||
struct list_head moves;
|
struct list_head moves;
|
||||||
} pos_t;
|
} pos_t;
|
||||||
|
Reference in New Issue
Block a user