commit of hell
This commit is contained in:
147
src/board.h
147
src/board.h
@@ -1,56 +1,149 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wchar.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
80
src/chess.c
80
src/chess.c
@@ -11,9 +11,11 @@
|
||||
#include <stdint.h> /* int32_t */
|
||||
#include <stdio.h> /* printf, scanf */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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; i<BOARD_SIZE; i++) {
|
||||
n = n*33+(size_t)b[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
struct boardset_entry {
|
||||
Board board;
|
||||
int n;
|
||||
struct boardset_entry* next;
|
||||
};
|
||||
|
||||
struct boardset {
|
||||
struct boardset_entry* entries[SET_SIZE];
|
||||
};
|
||||
|
||||
static void boardset_reset(struct boardset* bs)
|
||||
{
|
||||
for (size_t i=0; i < sizeof bs->entries / 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<BOARD_SIZE; i++) {
|
||||
@@ -942,6 +1013,7 @@ static void print_debug(struct game_state* g)
|
||||
|
||||
static void sigint_handler(int signal)
|
||||
{
|
||||
(void)signal;
|
||||
paint_board(&sigint_state_copy, -1, -1);
|
||||
print_debug(&sigint_state_copy);
|
||||
dump_game_state(&sigint_state_copy);
|
||||
@@ -1047,7 +1119,7 @@ int main()
|
||||
while (true) {
|
||||
printf("============================\n");
|
||||
paint_board(&state, from, to);
|
||||
printf("est. score: %lf", heuristic(&state, 0));
|
||||
printf("est. score: %lf\n", heuristic(&state, 0));
|
||||
//print_debug(&state);
|
||||
//dump_game_state(&state);
|
||||
|
||||
|
||||
26
src/map.h
26
src/map.h
@@ -1,20 +1,14 @@
|
||||
|
||||
|
||||
enum chess_piece {
|
||||
EMPTY = 0,
|
||||
KING = 1,
|
||||
QUEEN = 2,
|
||||
ROOK = 3,
|
||||
BISHOP = 4,
|
||||
KNIGHT = 5,
|
||||
PAWN = 6,
|
||||
PIECE_COUNT,
|
||||
};
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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];
|
||||
|
||||
Reference in New Issue
Block a user