summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/bitboard.h87
-rw-r--r--include/engine/moves.h81
-rw-r--r--include/fen.h12
-rw-r--r--include/ints.h20
-rw-r--r--include/ipc.h78
-rw-r--r--include/uci.h8
-rw-r--r--include/uci/command.h21
-rw-r--r--include/uci/response.h24
-rw-r--r--include/uci/state.h122
9 files changed, 453 insertions, 0 deletions
diff --git a/include/bitboard.h b/include/bitboard.h
new file mode 100644
index 0000000..ecd8c35
--- /dev/null
+++ b/include/bitboard.h
@@ -0,0 +1,87 @@
+#ifndef BITBOARD_H
+#define BITBOARD_H
+
+#include "ints.h"
+#include <stdbool.h>
+
+typedef u64 bitboard_t;
+
+enum {
+ WHITE_KING,
+ WHITE_QUEEN,
+ WHITE_ROOK,
+ WHITE_BISHOP,
+ WHITE_KNIGHT,
+ WHITE_PAWN,
+ BLACK_KING,
+ BLACK_QUEEN,
+ BLACK_ROOK,
+ BLACK_BISHOP,
+ BLACK_KNIGHT,
+ BLACK_PAWN,
+ PIECE_TYPE_COUNT,
+};
+
+enum {
+ WHITE_SHORT_CASTLE = 1 << 0,
+ WHITE_LONG_CASTLE = 1 << 1,
+ BLACK_SHORT_CASTLE = 1 << 2,
+ BLACK_LONG_CASTLE = 1 << 3,
+};
+
+enum {
+ WHITE_TURN,
+ BLACK_TURN,
+};
+
+#define BITMASK_RANK_1 255ULL
+#define BITMASK_RANK_2 65280ULL
+#define BITMASK_RANK_3 16711680ULL
+#define BITMASK_RANK_4 4278190080ULL
+#define BITMASK_RANK_5 1095216660480ULL
+#define BITMASK_RANK_6 280375465082880ULL
+#define BITMASK_RANK_7 71776119061217280ULL
+#define BITMASK_RANK_8 18374686479671623680ULL
+#define BITMASK_FILE_A 72340172838076673ULL
+#define BITMASK_FILE_B 144680345676153346ULL
+#define BITMASK_FILE_C 289360691352306692ULL
+#define BITMASK_FILE_D 578721382704613384ULL
+#define BITMASK_FILE_E 1157442765409226768ULL
+#define BITMASK_FILE_F 2314885530818453536ULL
+#define BITMASK_FILE_G 4629771061636907072ULL
+#define BITMASK_FILE_H 9259542123273814144ULL
+
+#define occupied_by(bitboard, index) (bitboard & ((bitboard_t)1 << index))
+
+typedef struct {
+ bitboard_t bitboards[PIECE_TYPE_COUNT];
+ u8 castling;
+ u8 turn;
+ u8 passantable_file;
+ u16 halfmove_clock;
+ u16 fullmove_clock;
+} position_t;
+
+position_t position_starting();
+void assert_valid_position(position_t position);
+bool check_valid_position(position_t position);
+#define whites(position) \
+ position.bitboards[WHITE_KING] | \
+ position.bitboards[WHITE_QUEEN] | \
+ position.bitboards[WHITE_ROOK] | \
+ position.bitboards[WHITE_BISHOP] | \
+ position.bitboards[WHITE_KNIGHT] | \
+ position.bitboards[WHITE_PAWN]
+
+#define blacks(position) \
+ position.bitboards[BLACK_KING] | \
+ position.bitboards[BLACK_QUEEN] | \
+ position.bitboards[BLACK_ROOK] | \
+ position.bitboards[BLACK_BISHOP] | \
+ position.bitboards[BLACK_KNIGHT] | \
+ position.bitboards[BLACK_PAWN]
+
+
+void print_bitboard(bitboard_t bitboard);
+
+#endif // BITBOARD_H
diff --git a/include/engine/moves.h b/include/engine/moves.h
new file mode 100644
index 0000000..86c4844
--- /dev/null
+++ b/include/engine/moves.h
@@ -0,0 +1,81 @@
+#ifndef MOVES_H
+#define MOVES_H
+
+#include "../ints.h"
+#include "../bitboard.h"
+
+typedef u8 square_t;
+
+// think about the chess move notation
+// e4, Nf6, Qh3+, Qe1#, a8=Q, i need to store the information needed to
+// recreate this in move_t
+enum {
+ MOVE_CAPTURE = 1,
+ MOVE_SHORT_CASTLE = 1 << 1,
+ MOVE_LONG_CASTLE = 1 << 2,
+
+ // technically these promotation flags can be compressed to only use 2 bits..
+ MOVE_PROMOTE_Q = 1 << 3, // 1 << 5
+ MOVE_PROMOTE_R = 1 << 4, // 2 << 5
+ MOVE_PROMOTE_B = 1 << 5, // 3 << 5
+ MOVE_PROMOTE_N = 1 << 6, // 4 << 5 ? nvm it uses 3
+ MOVE_EN_PASSANT = 1 << 7,
+ MOVE_CHECK = 1 << 8,
+};
+
+typedef struct {
+ square_t from;
+ square_t to;
+ u16 flags;
+} move_t;
+void position_make_move(position_t* position, move_t* move);
+
+typedef struct {
+ move_t* moves;
+ u32 length;
+ u32 capacity;
+} moves_t;
+
+moves_t moves_init();
+moves_t moves_init_wcapacity(u32 capacity);
+moves_t moves_empty();
+
+struct add_move_params {
+ u16 flags;
+};
+#define add_move(moves, from, to, ...) _add_move(\
+ moves, \
+ from, \
+ to, \
+ (struct add_move_params) { .flags = 0, __VA_ARGS__ }\
+)
+void _add_move(
+ moves_t* moves,
+ square_t from,
+ square_t to,
+ struct add_move_params params
+);
+
+void get_pawn_moves(moves_t* moves, position_t position);
+void get_knight_moves(moves_t* moves, position_t position);
+void get_king_moves(moves_t* moves, position_t position);
+void get_rook_moves(moves_t* moves, position_t position);
+void get_bishop_moves(moves_t* moves, position_t position);
+void get_queen_moves(moves_t* moves, position_t position);
+
+void get_moves(moves_t* moves, position_t position);
+
+void __forloop_rook_moves_gen(
+ moves_t* moves,
+ bitboard_t friendly_type,
+ bitboard_t friendly_pieces,
+ bitboard_t enemy_pieces
+);
+void __forloop_bishop_moves_gen(
+ moves_t* moves,
+ bitboard_t friendly_type,
+ bitboard_t friendly_pieces,
+ bitboard_t enemy_pieces
+);
+
+#endif // !MOVES_H
diff --git a/include/fen.h b/include/fen.h
new file mode 100644
index 0000000..d45240e
--- /dev/null
+++ b/include/fen.h
@@ -0,0 +1,12 @@
+#ifndef FEN_H
+#define FEN_H
+
+#include "bitboard.h"
+
+struct fen_load {
+ bool failed;
+ position_t position;
+};
+struct fen_load load_fen(const char* fen);
+
+#endif // FEN_H
diff --git a/include/ints.h b/include/ints.h
new file mode 100644
index 0000000..4a0cfe3
--- /dev/null
+++ b/include/ints.h
@@ -0,0 +1,20 @@
+#ifndef INTS_H
+#define INTS_H
+
+#include <stdint.h>
+#include <inttypes.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef __uint128_t u128;
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+typedef __int128_t i128;
+typedef float f32;
+typedef double f64;
+
+#endif // !INTS_H
diff --git a/include/ipc.h b/include/ipc.h
new file mode 100644
index 0000000..90a2bcc
--- /dev/null
+++ b/include/ipc.h
@@ -0,0 +1,78 @@
+#ifndef IPC_H
+#define IPC_H
+
+// NOT TRUE IPC: I REALISED I AM STUPID AND COULD HAVE JUST USED THREADS
+
+#include <sys/mman.h>
+#include <stdlib.h>
+
+#include "fen.h"
+#include "uci/state.h"
+
+typedef struct {
+ struct uci_move *moves;
+ int count;
+ int capacity;
+} comm_moves;
+
+struct engine_message {
+ int id;
+
+ int ready;
+
+ int depth;
+ int seldepth;
+ int multipv;
+ int score_cp;
+ int nodes;
+ int nps;
+ int hashfull;
+ int tbhits;
+ int time;
+
+ int mate;
+ bool node_limit;
+ comm_moves pv;
+
+ struct uci_move best_move;
+ struct uci_move ponder;
+
+ struct engine_message *next;
+};
+
+typedef struct {
+ struct engine_message **data;
+ int count;
+} engine_messages;
+
+enum { MESSAGE_FILLED, MESSAGE_READ, MESSAGE_PROCESSED };
+typedef struct {
+ engine_messages *engine_messages;
+ uci_state state;
+ int uci_state_initialized;
+ int uci_message_ready;
+ struct fen_load from_position;
+ comm_moves moves;
+} comms;
+
+comm_moves comm_moves_init();
+void add_comm_move(comm_moves *moves, struct uci_move move);
+
+struct go_args {
+ comm_moves searchmoves;
+ bool ponder;
+ int wtime;
+ int btime;
+ int winc;
+ int binc;
+ int movestogo;
+ int depth;
+ int nodes;
+ int mate;
+ int movetime;
+ bool infinite;
+ int perft;
+};
+bool should_continue(struct engine_message *message, struct go_args* go);
+
+#endif // IPC_H
diff --git a/include/uci.h b/include/uci.h
new file mode 100644
index 0000000..b3ee4cc
--- /dev/null
+++ b/include/uci.h
@@ -0,0 +1,8 @@
+#ifndef UCI_H
+#define UCI_H
+
+#include "ipc.h"
+
+void *uci(void *com);
+
+#endif // UCI_H
diff --git a/include/uci/command.h b/include/uci/command.h
new file mode 100644
index 0000000..ba9c51d
--- /dev/null
+++ b/include/uci/command.h
@@ -0,0 +1,21 @@
+#ifndef UCI_COMMAND_H
+#define UCI_COMMAND_H
+
+#define MAX_TOKEN_SIZE 32
+
+typedef struct {
+ char root[MAX_TOKEN_SIZE];
+ int args_count;
+ int args_capacity;
+ char* args;
+ bool empty;
+} ucicmd;
+
+ucicmd ucicmd_init();
+void ucicmd_add(ucicmd* cmd, const char* token);
+void ucicmd_set_root(ucicmd* cmd, const char* token);
+void ucicmd_append_arg(ucicmd* cmd, const char* token);
+char* ucicmd_get_arg(ucicmd cmd, int i);
+void ucicmd_deinit(ucicmd cmd);
+
+#endif // UCI_COMMAND_H
diff --git a/include/uci/response.h b/include/uci/response.h
new file mode 100644
index 0000000..320b1f0
--- /dev/null
+++ b/include/uci/response.h
@@ -0,0 +1,24 @@
+#ifndef RESPONSE_H
+#define RESPONSE_H
+
+#include "command.h"
+#include "state.h"
+#include "../ipc.h"
+
+void handle_uci(
+ uci_state *state,
+ engine_messages* engine_message,
+ ucicmd cmd
+);
+void handle_initial(uci_state *state, ucicmd cmd);
+void handle_idle(uci_state *state, ucicmd cmd);
+void handle_sync(uci_state *state, ucicmd cmd);
+void handle_ping(uci_state *state, ucicmd cmd);
+void handle_active(
+ uci_state *state,
+ engine_messages* engine_message,
+ ucicmd cmd
+);
+void handle_halt(uci_state *state, ucicmd cmd);
+
+#endif // RESPONSE_H
diff --git a/include/uci/state.h b/include/uci/state.h
new file mode 100644
index 0000000..a1df891
--- /dev/null
+++ b/include/uci/state.h
@@ -0,0 +1,122 @@
+#ifndef UCI_STATE_H
+#define UCI_STATE_H
+
+#include <stdatomic.h>
+#include "../fen.h"
+
+typedef struct {
+ char* data;
+ int length;
+} str_t;
+
+typedef bool check_t;
+typedef int spin_t;
+typedef int combo_t;
+// the button isn't actually a value thing
+// it's more like an event.
+// so we parse a button type, we set this to true, handle it
+// then set it to false again
+typedef bool button_t;
+
+typedef struct {
+ char** combination;
+ int count;
+ int default_index;
+} option_combo_setting_t;
+typedef struct {
+ int min;
+ int max;
+ int default_value;
+} option_spin_setting_t;
+enum { OPTION_SPIN, OPTION_COMBO, OPTION_CHECK, OPTION_STRING, OPTION_BUTTON };
+typedef struct {
+ char option_name[32];
+ int type;
+ union {
+ option_combo_setting_t combo;
+ option_spin_setting_t spin;
+ bool check_default;
+ const char* string_default;
+ } data;
+ union {
+ combo_t *combo;
+ spin_t *spin;
+ check_t *check;
+ str_t *string;
+ button_t *button;
+ } value;
+} option_setting_t;
+
+option_setting_t option_setting_combo(
+ char* option_name,
+ char** combinations,
+ int combinations_count,
+ int default_index,
+ combo_t *combo
+);
+option_setting_t option_setting_spin(
+ const char* option_name,
+ int min,
+ int max,
+ int default_value,
+ spin_t *spin
+);
+option_setting_t option_setting_check(
+ const char* option_name,
+ bool default_value,
+ check_t *check
+);
+option_setting_t option_setting_string(
+ const char* option_name,
+ const char* default_value,
+ str_t *string
+);
+option_setting_t option_setting_button(
+ const char* option_name,
+ button_t *button
+);
+
+typedef struct {
+ char name[32];
+ char author[32];
+ bool debug;
+
+ atomic_int go;
+ atomic_int go_ready_receive;
+ atomic_int quit;
+ atomic_int stop;
+ atomic_int cleanup;
+
+ void* go_args; // TODO: fix the information flow so i don't need to do this trick
+ position_t position;
+ struct uci_move *moves;
+ int moves_count;
+
+ option_setting_t option_settings[11];
+
+ // options
+ spin_t threads;
+ spin_t hash;
+ button_t clear_hash;
+ // str_t nalimovpath;
+ // spin_t nalimovcache;
+ // check_t ponder;
+ // check_t ownbook;
+ // spin_t multipv;
+ check_t uci_showcurrline;
+ check_t uci_showrefutations;
+ check_t uci_limitstrength;
+ spin_t uci_elo;
+ check_t uci_analysemode;
+ str_t uci_opponent;
+ str_t uci_engineabout;
+ // str_t uci_shredderbasespath;
+ str_t uci_setpositionvalue;
+} uci_state;
+
+struct uci_move {
+ int from;
+ int to;
+};
+
+#endif // UCI_STATE_H