board.c (6058B)
1 #include <ctype.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 #include <cul/assert.h> 6 #include <cul/mem.h> 7 8 #include "board.h" 9 #include "utils.h" 10 #include "zobrist.h" 11 12 Board *board_new(void) { 13 Board *p; 14 NEW0(p); 15 return p; 16 } 17 18 void board_free(Board **p) { FREE(*p); } 19 20 void board_copy(const Board *self, Board *dest) { *dest = *self; } 21 22 Square board_enpassant(const Board *self) { return self->enpassant; } 23 eCastle board_castle(const Board *self) { return self->castle; } 24 eColor board_side(const Board *self) { return self->side; } 25 U64 board_color(const Board *self, eColor color) { return self->color[color]; } 26 U64 board_piece(const Board *self, ePiece piece) { return self->piece[piece]; } 27 U64 board_hash(const Board *self) { return self->hash; } 28 29 U64 board_occupancy(const Board *self) { 30 return self->color[WHITE] | self->color[BLACK]; 31 } 32 33 U64 board_pieceSet(const Board *self, Piece piece) { 34 return self->piece[piece_piece(piece)] & self->color[piece_color(piece)]; 35 } 36 37 void board_color_pop(Board *self, eColor color, Square target) { 38 bit_pop(self->color[color], target); 39 } 40 41 void board_color_set(Board *self, eColor color, Square target) { 42 bit_set(self->color[color], target); 43 } 44 45 U64 board_color_get(const Board *self, eColor color, Square target) { 46 return bit_get(self->color[color], target); 47 } 48 49 int board_piece_get(const Board *self, Square square) { 50 for (int i = 0; i < 6; i++) 51 if (bit_get(self->piece[i], square)) return i; 52 return -1; 53 } 54 55 void board_piece_pop(Board *self, Piece piece, Square square) { 56 bit_pop(self->piece[piece_piece(piece)], square); 57 bit_pop(self->color[piece_color(piece)], square); 58 } 59 60 void board_piece_set(Board *self, Piece piece, Square square) { 61 bit_set(self->piece[piece_piece(piece)], square); 62 bit_set(self->color[piece_color(piece)], square); 63 } 64 65 U64 board_piece_attacks(const Board *self, Piece piece, Square src) { 66 return piece_attacks(piece)(src, board_occupancy(self)); 67 } 68 69 int board_isCheck(const Board *self) { 70 U64 king = self->piece[KING] & self->color[self->side]; 71 return board_square_isAttack(self, bit_lsb_index(king), !self->side); 72 } 73 int board_square_isOccupied(const Board *self, Square square) { 74 return bit_get(board_occupancy(self), square); 75 } 76 77 int board_square_isAttack(const Board *self, Square square, eColor side) { 78 U64 occupancy = self->color[WHITE] | self->color[BLACK]; 79 80 for (int i = KING; i >= PAWN; i--) { 81 if (piece_attacks(piece_get(i, !side))(square, occupancy) & 82 self->piece[i] & self->color[side]) 83 return 1; 84 } 85 86 return 0; 87 } 88 89 void board_side_switch(Board *self) { 90 self->side = !self->side; 91 self->hash ^= zobrist_key_side(); 92 } 93 94 void board_enpassant_set(Board *self, Square target) { 95 if (self->enpassant != no_sq) 96 self->hash ^= zobrist_key_enpassant(self->enpassant); 97 98 if (target != no_sq) self->hash ^= zobrist_key_enpassant(target); 99 self->enpassant = target; 100 } 101 102 void board_castle_and(Board *self, int exp) { self->castle &= exp; } 103 104 Piece board_square_piece(const Board *self, Square square, eColor color) { 105 for (ePiece i = 0; i < 6; i++) 106 if (bit_get(self->piece[i], square)) return piece_get(i, color); 107 return NULL; 108 } 109 110 Board *board_from_FEN(Board *board, const char *fen) { 111 if (!board) NEW(board); 112 113 memset(board, 0, sizeof(*board)); 114 115 board->side = -1; 116 board->enpassant = no_sq; 117 board->castle = 0; 118 119 int file = 0, rank = 7; 120 for (Piece piece; *fen != ' '; fen++) { 121 Square square = rank * 8 + file; 122 if (isalpha(*fen)) { 123 if (!(piece = piece_from_code(*fen))) assert(0); 124 bit_set(board->color[piece_color(piece)], square); 125 bit_set(board->piece[piece_piece(piece)], square); 126 file++; 127 } else if (isdigit(*fen)) { 128 file += *fen - '0'; 129 } else if (*fen == '/') { 130 file = 0; 131 rank--; 132 } else { 133 assert(0); 134 } 135 } 136 137 fen++; 138 if (*fen == 'w') 139 board->side = WHITE; 140 else if (*fen == 'b') 141 board->side = BLACK; 142 else 143 assert(0); 144 145 for (fen += 2; *fen != ' '; fen++) { 146 switch (*fen) { 147 case 'K': 148 board->castle |= WK; 149 break; 150 case 'Q': 151 board->castle |= WQ; 152 break; 153 case 'k': 154 board->castle |= BK; 155 break; 156 case 'q': 157 board->castle |= BQ; 158 break; 159 case '-': 160 break; 161 default: 162 assert(0); 163 } 164 } 165 166 fen++; 167 if (*fen != '-') { 168 board->enpassant = coordinates_to_square(fen); 169 } 170 171 board->hash = zobrist_hash(board); 172 return board; 173 } 174 175 void board_print(const Board *self) { 176 for (int rank = 0; rank < 8; rank++) { 177 for (int file = 0; file < 8; file++) { 178 Square square = (7 - rank) * 8 + file; 179 Piece piece = NULL; 180 181 int color = -1; 182 if (bit_get(self->color[WHITE], square)) 183 color = WHITE; 184 else if (bit_get(self->color[BLACK], square)) 185 color = BLACK; 186 187 if (color != -1) { 188 for (int piece_index = 0; piece_index < 6; piece_index++) { 189 if (bit_get(self->piece[piece_index], square)) { 190 piece = piece_get(piece_index, color); 191 break; 192 } 193 } 194 } 195 196 if (!file) printf(" %d ", 8 - rank); 197 198 printf("%c ", (piece) ? piece_asci(piece) : '.'); 199 } 200 printf("\n"); 201 } 202 printf(" A B C D E F G H\n"); 203 printf(" Side: %s\n", (self->side == WHITE) ? "white" : "black"); 204 printf("Enpassant: %s\n", square_to_coordinates[self->enpassant]); 205 printf(" Castling: %c%c%c%c\n", (self->castle & WK) ? 'K' : '-', 206 (self->castle & WQ) ? 'Q' : '-', (self->castle & BK) ? 'k' : '-', 207 (self->castle & BQ) ? 'q' : '-'); 208 printf(" Hash: %llx\n", self->hash); 209 printf("\n"); 210 }