From a14da2fe3864712dab4e7c4cfb5c323026d668de Mon Sep 17 00:00:00 2001 From: Aargh Rai Date: Fri, 10 Jul 2026 16:01:57 +0530 Subject: moving header files to include directory & moving resources in it's own directory i know currently there is race condition, but the code is getting too messy, i will continue to this after i make a vis tool to analyse how i should split up files & stuff the code rn needs intense restructing for it to make any more progress --- include/bitboard.h | 87 +++++++++++++++++++++++++++++++++++ include/engine/moves.h | 81 ++++++++++++++++++++++++++++++++ include/fen.h | 12 +++++ include/ints.h | 20 ++++++++ include/ipc.h | 78 +++++++++++++++++++++++++++++++ include/uci.h | 8 ++++ include/uci/command.h | 21 +++++++++ include/uci/response.h | 24 ++++++++++ include/uci/state.h | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 453 insertions(+) create mode 100644 include/bitboard.h create mode 100644 include/engine/moves.h create mode 100644 include/fen.h create mode 100644 include/ints.h create mode 100644 include/ipc.h create mode 100644 include/uci.h create mode 100644 include/uci/command.h create mode 100644 include/uci/response.h create mode 100644 include/uci/state.h (limited to 'include') 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 + +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 +#include + +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 +#include + +#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 +#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 -- cgit v1.2.3