stellar

Stellar - Chess engine written in C
Log | Files | Refs

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 }