ext/board.c in chess-0.1.3 vs ext/board.c in chess-0.1.4

- old
+ new

@@ -5,10 +5,11 @@ * This code is under LICENSE LGPLv3 */ #include "board.h" +// Initialize the board void init_board (Board *board) { memcpy (board->placement, "RNBQKBNRPPPPPPPP\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0pppppppprnbqkbnr", 64); board->active_color = WHITE; @@ -30,10 +31,11 @@ board->king[WHITE] = 0x0000000000000010; board->king[BLACK] = 0x1000000000000000; set_occupied (board); } +// Set helpers bitboards (white pieces, black pieces, occupied squares). void set_occupied (Board *board) { board->pieces[WHITE] = board->pawns[WHITE] | board->rooks[WHITE] @@ -48,10 +50,11 @@ | board->queens[BLACK] | board->king[BLACK]; board->occupied = board->pieces[WHITE] | board->pieces[BLACK]; } +// Board to string. char* print_board (Board *board) { char *s = (char *) malloc (251); int si = 0; @@ -70,10 +73,11 @@ } sprintf (&s[si], "\e[37m a b c d e f g h\e[0m"); return s; } +// Given a square returns its color (white is 0, black is 1). int get_color (Board *board, int square) { int piece = board->placement[square]; if (piece) @@ -83,10 +87,11 @@ return BLACK; else return -1; } +// Given a piece returns the piece's bitboard. bboard* get_piece_bitboard (Board *board, char piece) { // TODO: we can avoid this swith using an array of boards, the index is the piece type switch (piece) @@ -105,16 +110,19 @@ case 'k': return &board->king[BLACK]; default: return 0; } } +// Given a square (0..63) retuns the piece's bitboard in that square. bboard* get_bitboard (Board *board, int square) { return get_piece_bitboard (board, board->placement[square]); } +// Returns the bitboard with the xray that start from square. If only_attack use +// only pawns attack squares. bboard xray (Board *board, int from, bool only_attack) { switch (board->placement[from]) { @@ -138,11 +146,12 @@ case 'k': return xray_king (from); default: return 0; } } -// All xray of color pieces + +// Returns the bitboard with all the xray that start from the color pieces. bboard all_xray (Board *board, int color, bool only_attack) { bboard x = EMPTY_BOARD; // xray for all pieces for (int i = 0; i < 64; i++) @@ -153,17 +162,19 @@ x |= xray (board, i, only_attack); } return x; } -// All xray of color pieces with friends square removed +// Returns the bitboard with all the xray that start from the color pieces with +// friend squares removed. bboard -all_xray_friend (Board *board, int color, bool only_attack) +all_xray_without_friends (Board *board, int color, bool only_attack) { return all_xray (board, color, only_attack) & ~board->pieces[color]; } +// Returns a new board with the piece in square position removed. void remove_piece (Board *board, int square, Board *new_board) { memcpy (new_board, board, sizeof (Board)); if (board->placement[square]) @@ -172,11 +183,12 @@ new_board->placement[square] = 0; set_occupied (new_board); } } -// return the squares of pieces as piece that can capture in to +// Returns the squares of the same pieces of color and its size that can capture +// the square. If piece_filter consider only that kind of pieces. int same_pieces_that_can_capture_a_square (Board *board, int color, int square, int *pieces, char piece_filter) { int index = 0; char p; @@ -193,38 +205,42 @@ } } return index; } +// Returns true if square can be captured from color pieces. bool capture (Board *board, int color, int square) { - return all_xray_friend (board, color, FALSE) & (1ULL << square) ? TRUE : FALSE; + return all_xray_without_friends (board, color, FALSE) & (1ULL << square) ? TRUE : FALSE; } -// If there is a piece that can capture the to square without put its king in check return true +// Returns true if there is a piece that can capture the square without put its +// king in check. bool pieces_can_safe_capture (Board *board, int color, int square) { int pieces[16]; return same_pieces_that_can_capture_a_square (board, color, square, pieces, 0) > 0; } +// Returns true if the king color is in check. bool king_in_check (Board *board, int color) { - return all_xray_friend (board, !color, TRUE) & board->king[color] ? TRUE : FALSE; + return all_xray_without_friends (board, !color, TRUE) & board->king[color] ? TRUE : FALSE; } -// Assumes that king is in check +// Returns true if the king color is in check. Assumes that the king is in +// check. bool king_in_checkmate (Board *board, int color) { int king_square = square2 (board->king[color]); bboard king = xray_king (king_square) & ~board->pieces[color]; Board board_without_king; - remove_piece (board, king_square, &board_without_king); // King cant be auto-shielded xray + remove_piece (board, king_square, &board_without_king); // King can't be auto-shielded xray bboard attackers = all_xray (&board_without_king, !color, TRUE); // If king can move return false if (king & ~attackers) return FALSE; int pieces[16]; @@ -235,11 +251,12 @@ int attacker = pieces[0]; // Test if there is a piece that can capture the attacker without put its king in check return false if (pieces_can_safe_capture (board, color, attacker)) return FALSE; // Test if there is an en passant capture - if (have_en_passant2 (board, attacker)) + if (have_en_passant (board, attacker + 1, board->en_passant) || + have_en_passant (board, attacker - 1, board->en_passant)) return FALSE; // Test if attack can be shielded bboard slide = EMPTY_BOARD; int i; for (i = 0; i < 8; i++) @@ -247,11 +264,11 @@ slide = sliding_attacks (1ULL << attacker, FULL_BOARD, i); if (slide & 1ULL << king_square) break; } bboard attack = xray (board, attacker, TRUE) & slide; - bboard defend = all_xray_friend (board, color, FALSE); + bboard defend = all_xray_without_friends (board, color, FALSE); bboard shield = attack & defend; if (shield) { int s[64]; int n; @@ -261,10 +278,11 @@ return FALSE; } return TRUE; } +// Returns true if the color pieces are in stale. bool stalemate (Board *board, int color) { int s[64]; int n; @@ -283,10 +301,11 @@ } } return TRUE; } +// Returns true if there are insufficient material to make a checkmate. bool insufficient_material (Board *board) { if (board->queens[WHITE] || board->queens[BLACK] || board->rooks[WHITE] || board->rooks[BLACK] @@ -308,20 +327,45 @@ { if ((only_white_squares(board->bishops[WHITE]) && only_white_squares(board->bishops[BLACK])) || (only_black_squares(board->bishops[WHITE]) && only_black_squares(board->bishops[BLACK]))) return TRUE; } + // TODO more bishops on same color square return FALSE; } +// Returns true if on the board there are only the two kings. bool +only_kings (Board *board) +{ + return !board->pawns[WHITE] && !board->pawns[BLACK] && + !board->rooks[WHITE] && !board->rooks[BLACK] && + !board->knights[WHITE] && !board->knights[BLACK] && + !board->bishops[WHITE] && !board->bishops[BLACK] && + !board->queens[WHITE] && !board->queens[BLACK]; +} + +// Returns true if fifty move rule is available. +bool fifty_move_rule (Board *board) { return board->halfmove_clock >= 50; } +// Returns true if the move from-to can not promote the pawn. bool +invalid_promotion (Board *board, int from, int to) +{ + if (toupper (board->placement[from]) != 'P') + return TRUE; + if ((board->active_color ? 0xffffffffffffff00 : 0x00ffffffffffffff) & (1ULL << to)) + return TRUE; + return FALSE; +} + +// Returns true if the move from-to is pseudo legal. +bool pseudo_legal_move (Board *board, int from, int to) { // Piece in from square is the right color if (get_color (board, from) != board->active_color) return FALSE; @@ -334,11 +378,13 @@ // The move is legal? bboard x = xray (board, from, FALSE) & ~board->pieces[board->active_color]; return x & (1ULL << to) ? TRUE : FALSE; } -void +// Returns true if the move piece-dis-to is legal. Returns also [from, to] +// coordinate (0..63). Pseudo legal move check included. +bool get_coord (Board *board, char piece, const char *disambiguating, const char *to_coord, char promote_in, int *from, int *to) { int count = 0; char file, rank; bboard x; @@ -353,14 +399,14 @@ x = xray (board, i, FALSE) & ~board->pieces[c]; if (x & 1ULL << *to || have_en_passant (board, i, *to)) { file = square_to_file (i); rank = square_to_rank (i); - if (!strcmp (disambiguating, "") - || disambiguating[0] == file - || disambiguating[0] == rank - || (disambiguating[0] == file && disambiguating[1] == rank)) + if (!disambiguating + || disambiguating[0] == file + || disambiguating[0] == rank + || (disambiguating[0] == file && disambiguating[1] == rank)) { Board new_board; if (try_move (board, i, *to, promote_in, &new_board, 0, 0)) { *from = i; @@ -369,18 +415,27 @@ } } } } if (count != 1) - *from = *to = 0; + { + *from = *to = 0; + return FALSE; + } // For compatibility: if pawn capture a file disambiguating is required - else if (piece == 'P' && !strcmp (disambiguating, "")) - if (square_to_file (*from) != square_to_file (*to)) + if (piece == 'P' && !disambiguating && square_to_file (*from) != square_to_file (*to)) + { *from = *to = 0; + return FALSE; + } + return TRUE; } -// This function do not consider castling, this is handled separately. +// Returns true if the move from-to can be performed. Returns also the short +// algebraic chess notation of the move and the captured piece if occured. +// Assume that the move is pseudo legal. Do not consider castling, this is +// handled separately. bool try_move (Board *board, int from, int to, char promote_in, Board *new_board, char **move_done, char *capture) { memcpy (new_board, board, sizeof (Board)); *(get_bitboard (new_board, from)) ^= 1ULL << from; @@ -401,14 +456,11 @@ // Change placement new_board->placement[to] = new_board->placement[from]; new_board->placement[from] = 0; // Promotion check if (require_a_promotion (new_board)) - { - if (!promote (new_board, to, promote_in)) - return FALSE; - } + promote (new_board, to, promote_in); else promote_in = 0; // Set occupied pieces in new board set_occupied (new_board); // If king is in check can't move! @@ -418,10 +470,11 @@ if (move_done && capture) *move_done = get_notation (board, from, to, *capture, ep, promote_in, 0, 0); return TRUE; } +// Returns the short algebraic chess notation of the move from-to. char* get_notation (Board *board, int from, int to, int capture, int ep, char promotion, int check, int checkmate) { // Get short algebraic chess notation int i = 0; @@ -504,9 +557,10 @@ } notation[i] = '\0'; return notation; } +// Returns the fen string that rappresent the board. char* to_fen (Board *board) { // 1. Placement char placement[65];