diff --git a/src/board.h b/src/board.h index 756b31e..a293998 100644 --- a/src/board.h +++ b/src/board.h @@ -1,56 +1,149 @@ #pragma once +#include +#include +#include +#include +#include #include #include #include #include -typedef uint64_t bitmap_t; -typedef uint_fast8_t index_t; -typedef int_fast8_t piece_t; +typedef uint64_t bitmap_t; +typedef uint64_t index_t; +typedef uint64_t piece_t; -enum tile_info { - EMPTY = 0b0000, - KING = 0b0001, - QUEEN = 0b0010, - ROOK = 0b0011, - BISHOP = 0b0100, - KNIGHT = 0b0101, - PAWN = 0b0110, - COLOR_BIT = 0b1000, +#define TILE_BITS 4ULL - PIECE_UNKNOWN=-1 +enum piece : piece_t { + EMPTY = 0b0000ULL, + + W_KING = 0b0001ULL, + W_QUEEN = 0b0010ULL, + W_ROOK = 0b0011ULL, + W_BISHOP = 0b0100ULL, + W_KNIGHT = 0b0101ULL, + W_PAWN = 0b0110ULL, + W_PAWN_ENPASSENTABLE = 0b0111ULL, + + B_EMPTY = 0b1000ULL, + B_KING = 0b1001ULL, + B_QUEEN = 0b1010ULL, + B_ROOK = 0b1011ULL, + B_BISHOP = 0b1100ULL, + B_KNIGHT = 0b1101ULL, + B_PAWN = 0b1110ULL, + B_PAWN_ENPASSENTABLE = 0b1111ULL, + + BLACK = 0b1000ULL, + #define WHITE 0 +}; + +static const char * const piece_str[] = { + [EMPTY] = "EMPTY", + [W_KING] = "W_KING", + [W_QUEEN] = "W_QUEEN", + [W_ROOK] = "W_ROOK", + [W_BISHOP] = "W_BISHOP", + [W_KNIGHT] = "W_KNIGHT", + [W_PAWN] = "W_PAWN", + [W_PAWN_ENPASSENTABLE] = "W_PAWN (enpassentable)", + + [B_EMPTY] = "EMPTY (BLACK flag set)", + [B_KING] = "B_KING", + [B_QUEEN] = "B_QUEEN", + [B_ROOK] = "B_ROOK", + [B_BISHOP] = "B_BISHOP", + [B_KNIGHT] = "B_KNIGHT", + [B_PAWN] = "B_PAWN", + [B_PAWN_ENPASSENTABLE ] = "B_PAWN (enpassentable)", +}; + +static const wchar_t piece_symbol[] = { + [WHITE | 0] = ' ', + [W_KING] = 0x265A, + [W_QUEEN] = 0x265B, + [W_ROOK] = 0x265C, + [W_BISHOP] = 0x265D, + [W_KNIGHT] = 0x265E, + [W_PAWN] = 0x265F, + [W_PAWN_ENPASSENTABLE] = 0x265F, + [B_KING] = 0x265A, + [B_QUEEN] = 0x265B, + [B_ROOK] = 0x265C, + [B_BISHOP] = 0x265D, + [B_KNIGHT] = 0x265E, + [B_PAWN] = 0x265F, + [B_PAWN_ENPASSENTABLE] = 0x265F, }; struct board { - static_assert(sizeof(bitmap_t) == 64/8, "bitmap_t must be 64 bits long"); bitmap_t pieces[4]; // 4 bits correspond to 1 tile }; +static_assert(sizeof(((struct board*)0)->pieces) * CHAR_BIT == TILE_BITS*64, + "pieces must contain enough information to hold a 64 chessboard tiles"); +static_assert((sizeof(((struct board*)0)->pieces[0]) * CHAR_BIT) % TILE_BITS == 0, + "bitmap_t in bits must be divisible by TILE_BITS"); -static inline bitmap_t bit(index_t i) +static inline bitmap_t tile_mask(index_t i) { - return 0b111UL << 3*i; + return 0b1111ULL << (TILE_BITS*i); } -static bool is_white(piece_t piece) +static inline bool is_white(piece_t piece) { - return piece % 2 == 0; + return (piece & BLACK) == 0; } -static bool is_black(piece_t piece) +static inline bool is_black(piece_t piece) { - return piece % 2 == 1; + return (piece & BLACK) == BLACK; } -static piece_t piece_at(struct board* board, index_t tile) +static inline piece_t piece_at(struct board* board, index_t tile) { - for (size_t i = 0; i < sizeof board->pieces / board->pieces[0]; i++) { - if (bit(tile) & board->pieces[i]) { - return i; + static_assert(sizeof board->pieces[0] * CHAR_BIT == 64, "bad refactor"); + return (tile_mask(tile % (64/TILE_BITS)) & board->pieces[tile / (64/TILE_BITS)]) >> 4ULL*tile; +} + +static void paint_board(struct board* b) +{ + /* https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode + The unicode symbols for the pieces are calculated from adding + 0x2653 (#define'd as UNICODE_CHESS_SYMBOL) with the piece value. */ +#define BG_RED() printf("\033[48;2;150;150;0m") +#define BG_DARKBLUE() printf("\033[48;2;100;100;150m") +#define BG_LIGHTBLUE() printf("\033[48;2;150;150;200m") +#define FG_BLACK() printf("\033[38;2;0;0;0m") +#define FG_WHITE() printf("\033[38;2;255;255;255m") + for (int i = 7; i >= 0; i--) { + printf("\n %d ", i+1); // number coordinates + for (int j = 0; j < 8; j++) { + piece_t p = piece_at(b, i*8+j); + if ((i + j) % 2) { + BG_DARKBLUE(); + } else { + BG_LIGHTBLUE(); + } + + if (p == EMPTY) { + printf(" "); + continue; + } + if (is_white(p)) { + FG_WHITE(); + } else { + FG_BLACK(); + } + printf("%lc ", piece_symbol[p]); } + printf("\033[0m"); // reset text attributes } - return PIECE_UNKNOWN; + /* horizontal letter coordinates */ + printf("\n "); + for (int i = 0; i < 8; i++) + printf(" %c", 'a' + i); + printf("\n"); } - - diff --git a/src/chess.c b/src/chess.c index 02e74d8..6c4bd8c 100644 --- a/src/chess.c +++ b/src/chess.c @@ -11,9 +11,11 @@ #include /* int32_t */ #include /* printf, scanf */ #include +#include -#define MAX_DEPTH 4 +#define MAX_DEPTH 5 #define CHECKMATE_SCORE 100000 +#define SET_SIZE 4096 #define RANK ((index_t)8) #define COL ((index_t)1) @@ -171,7 +173,7 @@ static const double piece_position_bonus[PIECE_COUNT][BOARD_SIZE] = { }, [KING] = { /* A B C D E F G H */ - /* 1 */ 1.1, 1.1, 1.1, 1.0, 1.0, 1.0, 1.15, 1.15, + /* 1 */ 1.1, 1.1, 1.1, 1.0, 1.0, 1.0, 1.3, 1.15, /* 2 */ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, /* 3 */ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, /* 4 */ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, @@ -214,6 +216,75 @@ enum castle_type { CASTLE_QUEENSIDE = 2, }; +static bool board_equals(Board* b1, Board* b2) +{ + return memcmp(b1, b2, sizeof *b1) == 0; +} + +static size_t board_hash(Board* b) +{ + size_t n = 5381; + for (int i=0; ientries / sizeof *(bs->entries); i++) { + struct boardset_entry* next, *e = bs->entries[i]; + while (e) { + next = e->next; + free(e->board); + free(e); + e = next; + } + } +} + +static struct boardset_entry* boardset_get(struct boardset* bs, Board* b) +{ + size_t i = board_hash(b) % SET_SIZE; + + struct boardset_entry** bsentry = &(bs->entries[i]); + + while (*bsentry != NULL && !board_equals(b, &((*bsentry)->board))) { + *bsentry = (*bsentry)->next; + } + + if (*bsentry == NULL) { + *bsentry = calloc(sizeof *bsentry, 1); + if (bsentry == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } + } + + return *bsentry; +} + +int boardset_count(struct boardset* bs, Board* b) +{ + return boardset_get(bs, b)->n; +} + +void boardset_inc(struct boardset* bs, Board* b) +{ + boardset_get(bs, b)->n += 1; +} + + static inline bitmap_t bit(index_t i) { return 1UL << i; @@ -902,7 +973,7 @@ static double heuristic(struct game_state* g, int depth) return 0; if (checkmate(g)) - return g->player * -9999; + return g->player * -10000 * depth; double score = 0; for (index_t i=0; i +#include +#include +#include +#include +#include -static bool board_equals( +#define SET_SIZE 4096 +#define BOARD_SIZE 64 - - -struct board_map { - -}; +typedef int_fast8_t piece_t; +typedef piece_t Board[BOARD_SIZE];