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];