commit of hell
This commit is contained in:
147
src/board.h
147
src/board.h
@@ -1,56 +1,149 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
typedef uint64_t bitmap_t;
|
typedef uint64_t bitmap_t;
|
||||||
typedef uint_fast8_t index_t;
|
typedef uint64_t index_t;
|
||||||
typedef int_fast8_t piece_t;
|
typedef uint64_t piece_t;
|
||||||
|
|
||||||
enum tile_info {
|
#define TILE_BITS 4ULL
|
||||||
EMPTY = 0b0000,
|
|
||||||
KING = 0b0001,
|
|
||||||
QUEEN = 0b0010,
|
|
||||||
ROOK = 0b0011,
|
|
||||||
BISHOP = 0b0100,
|
|
||||||
KNIGHT = 0b0101,
|
|
||||||
PAWN = 0b0110,
|
|
||||||
COLOR_BIT = 0b1000,
|
|
||||||
|
|
||||||
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 {
|
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
|
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++) {
|
static_assert(sizeof board->pieces[0] * CHAR_BIT == 64, "bad refactor");
|
||||||
if (bit(tile) & board->pieces[i]) {
|
return (tile_mask(tile % (64/TILE_BITS)) & board->pieces[tile / (64/TILE_BITS)]) >> 4ULL*tile;
|
||||||
return i;
|
}
|
||||||
|
|
||||||
|
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 <stdint.h> /* int32_t */
|
||||||
#include <stdio.h> /* printf, scanf */
|
#include <stdio.h> /* printf, scanf */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define MAX_DEPTH 4
|
#define MAX_DEPTH 5
|
||||||
#define CHECKMATE_SCORE 100000
|
#define CHECKMATE_SCORE 100000
|
||||||
|
#define SET_SIZE 4096
|
||||||
|
|
||||||
#define RANK ((index_t)8)
|
#define RANK ((index_t)8)
|
||||||
#define COL ((index_t)1)
|
#define COL ((index_t)1)
|
||||||
@@ -171,7 +173,7 @@ static const double piece_position_bonus[PIECE_COUNT][BOARD_SIZE] = {
|
|||||||
},
|
},
|
||||||
[KING] = {
|
[KING] = {
|
||||||
/* A B C D E F G H */
|
/* 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,
|
/* 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,
|
/* 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,
|
/* 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,
|
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)
|
static inline bitmap_t bit(index_t i)
|
||||||
{
|
{
|
||||||
return 1UL << i;
|
return 1UL << i;
|
||||||
@@ -902,7 +973,7 @@ static double heuristic(struct game_state* g, int depth)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (checkmate(g))
|
if (checkmate(g))
|
||||||
return g->player * -9999;
|
return g->player * -10000 * depth;
|
||||||
|
|
||||||
double score = 0;
|
double score = 0;
|
||||||
for (index_t i=0; i<BOARD_SIZE; i++) {
|
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)
|
static void sigint_handler(int signal)
|
||||||
{
|
{
|
||||||
|
(void)signal;
|
||||||
paint_board(&sigint_state_copy, -1, -1);
|
paint_board(&sigint_state_copy, -1, -1);
|
||||||
print_debug(&sigint_state_copy);
|
print_debug(&sigint_state_copy);
|
||||||
dump_game_state(&sigint_state_copy);
|
dump_game_state(&sigint_state_copy);
|
||||||
@@ -1047,7 +1119,7 @@ int main()
|
|||||||
while (true) {
|
while (true) {
|
||||||
printf("============================\n");
|
printf("============================\n");
|
||||||
paint_board(&state, from, to);
|
paint_board(&state, from, to);
|
||||||
printf("est. score: %lf", heuristic(&state, 0));
|
printf("est. score: %lf\n", heuristic(&state, 0));
|
||||||
//print_debug(&state);
|
//print_debug(&state);
|
||||||
//dump_game_state(&state);
|
//dump_game_state(&state);
|
||||||
|
|
||||||
|
|||||||
26
src/map.h
26
src/map.h
@@ -1,20 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
enum chess_piece {
|
#include <stdint.h>
|
||||||
EMPTY = 0,
|
#include <stddef.h>
|
||||||
KING = 1,
|
#include <stdlib.h>
|
||||||
QUEEN = 2,
|
#include <stdio.h>
|
||||||
ROOK = 3,
|
#include <stdbool.h>
|
||||||
BISHOP = 4,
|
#include <string.h>
|
||||||
KNIGHT = 5,
|
|
||||||
PAWN = 6,
|
|
||||||
PIECE_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool board_equals(
|
#define SET_SIZE 4096
|
||||||
|
#define BOARD_SIZE 64
|
||||||
|
|
||||||
|
typedef int_fast8_t piece_t;
|
||||||
|
typedef piece_t Board[BOARD_SIZE];
|
||||||
struct board_map {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user