diff options
| author | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-13 21:58:18 +0530 |
|---|---|---|
| committer | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-13 21:58:18 +0530 |
| commit | f8c0dc54e36cc201c657aa12e5a22029b092e1bc (patch) | |
| tree | a0dd1a42c9681be98a7508c128db0dacacefc2e7 | |
| parent | 2e8b78ab0ef01eaacd8094ff839ac93b4451e9c3 (diff) | |
restructed all the files + uci done now
also broke the symbol analyser in the process, i didn't help much, i had
to pull out the pen & paper, but it made a cool graph never the less
multithreading was a pain! but it got it in the end
fixed the structs naming convention, if it's used outside by other
files, it's typedeffed, otherwise it's not
fixed the recursive imports issued i had in go_args*, where i was
casting it to void* in uci to make it work
now response.c doesn't deal with ipc, really happy with that change
now every single thing has its own responsibility
58 files changed, 1455 insertions, 1133 deletions
diff --git a/assets/board.js b/assets/board.js deleted file mode 100644 index 9c7b29d..0000000 --- a/assets/board.js +++ /dev/null @@ -1,262 +0,0 @@ -const assets = [ - "wk.webp", "wq.webp", "wr.png", "wb.webp", "wn.png", "wp.png", - "bk.webp", "bq.png", "br.webp", "bb.webp", "bn.webp", "bp.png" -].map(x => "./assets/pieces/" + x); -let hoveringPiece = -1; - -const bitboards = [ - 16n, - 8n, - 129n, - 36n, - 66n, - 65280n, - 1152921504606846976n, - 576460752303423488n, - 9295429630892703744n, - 2594073385365405696n, - 4755801206503243776n, - 71776119061217280n, -]; -const WHITE_KING = 0; -const WHITE_QUEEN = 1; -const WHITE_ROOK = 2; -const WHITE_BISHOP = 3; -const WHITE_KNIGHT = 4; -const WHITE_PAWN = 5; -const BLACK_KING = 6; -const BLACK_QUEEN = 7; -const BLACK_ROOK = 8; -const BLACK_BISHOP = 9; -const BLACK_KNIGHT = 10; -const BLACK_PAWN = 11; - -let counting_bitboard = 0n; -function trackBitboard(i, selected, output) { - const mask = 1n << BigInt(i); - if (selected) counting_bitboard |= mask; - else counting_bitboard &= ~mask; - output.textContent = counting_bitboard.toString(); -} - -function checkForPiece(square, bitIndex, set = true) { - for (let i = 0; i < bitboards.length; i++) { - const mask = bitboards[i]; - if ((mask >> BigInt(bitIndex)) & 1n) { - if (set) square.style.backgroundImage = `url(${assets[i]})`; - return i; - } - } - return null; -} - -function isYourTurn(piece) { - if (turn == "w") return piece < 6; - return piece >= 6; -} - -const selectedAction = trackBitboard; - -window.onkeydown = (e) => { - if (e.key == 'b') { - console.log(` -position.bitboards[WHITE_KING] = ${bitboards[0].toString()}ULL; -position.bitboards[WHITE_QUEEN] = ${bitboards[1].toString()}ULL; -position.bitboards[WHITE_ROOK] = ${bitboards[2].toString()}ULL; -position.bitboards[WHITE_BISHOP] = ${bitboards[3].toString()}ULL; -position.bitboards[WHITE_KNIGHT] = ${bitboards[4].toString()}ULL; -position.bitboards[WHITE_PAWN] = ${bitboards[5].toString()}ULL; -position.bitboards[BLACK_KING] = ${bitboards[6].toString()}ULL; -position.bitboards[BLACK_QUEEN] = ${bitboards[7].toString()}ULL; -position.bitboards[BLACK_ROOK] = ${bitboards[8].toString()}ULL; -position.bitboards[BLACK_BISHOP] = ${bitboards[9].toString()}ULL; -position.bitboards[BLACK_KNIGHT] = ${bitboards[10].toString()}ULL; -position.bitboards[BLACK_PAWN] = ${bitboards[11].toString()}ULL; - `) - } -} - -let validMoves = {}; -let renderingMoves = []; -let pickedUpFrom = -1; - -function updateRenderingMoves() { - for (let i = 0; i < 64; i++) { - const square = document.getElementById(`square-${i}`); - if (renderingMoves.includes(i)) square.children[0].classList.add("possible_move"); - else square.children[0].classList.remove("possible_move"); - } -} - -function handleTransmission(data) { - data = data.join(""); - for (let i = 0; i < data.length / 4; i++) { - const moveData = data.slice(4 * i, 4 * i + 4); - let from = parseInt(moveData.slice(0, 2)); - let to = parseInt(moveData.slice(2)); - - console.log(from, to, moveData); - - if (validMoves[from] == undefined) validMoves[from] = [] - validMoves[from].push(to); - } -} - -function calculateFen() { - let fen = "" - let empty = 0; - for (let i = 7; i >= 0; i--) { - for (let j = 0; j < 8; j++) { - const sqr = document.getElementById(`square-${8 * i + j}`).style.backgroundImage; - if (sqr.length == 0 || sqr.includes("none")) { - empty++; - continue; - } - if (empty != 0) { - fen += empty.toString(); - } - empty = 0; - let p = sqr[22]; - if (sqr[21] == "w") p = sqr[22].toUpperCase(); - fen += p; - } - if (empty != 0) { - fen += empty.toString(); - } - if (i == 0) continue; - empty = 0; - fen += "/"; - } - return fen; -} - -let turn = "w"; -let castling = "KQkq"; -let passant_square = "-"; -let halfmove = 0; -let fullmove = 1; -let socket; -let old_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; -function checkMoveMade(pieceMoved) { - let new_fen = calculateFen(); - if (new_fen == old_fen.split(" ")[0]) return; - old_fen = new_fen; - halfmove++; - console.log(pieceMoved) - if (pieceMoved == WHITE_PAWN || pieceMoved == BLACK_PAWN) halfmove = 0; - if (turn == "b") fullmove++; - turn = turn == "w" ? "b" : "w"; - old_fen = `${new_fen} ${turn} ${castling} ${passant_square} ${halfmove} ${fullmove}`; - validMoves = {}; - console.log(old_fen); - socket.send(old_fen); -} - -function connectSocket() { - socket = new WebSocket("ws://localhost:3456"); - let data = []; - socket.onmessage = e => { - console.log(e); - if (e.data == "END-TRANSMISSION") { - handleTransmission(data); - data = []; - } else { - data.push(e.data); - } - } - socket.onopen = () => { - console.log(old_fen); - socket.send(old_fen); - } - socket.onerror = e => { - console.log("error", e); - }; -} - -window.onload = () => { - connectSocket(); - socket.onclose = e => { - console.log("closed", e.code, e.reason); - }; - - const output = document.getElementById("output"); - const board = document.getElementById("board"); - for (let i = 0; i < 64; i++) { - if (i % 8 == 0) { - const label = document.createElement("div"); - label.classList.add("label"); - label.textContent = 8 - Math.round(i / 8); - board.appendChild(label); - } - const square = document.createElement("div"); - square.classList.add("square"); - - const renderingMoveMarker = document.createElement("div"); - renderingMoveMarker.classList.add("rendering_marker"); - square.appendChild(renderingMoveMarker); - - const shift = Math.floor(i / 8); - square.classList.add((i + shift) % 2 ? "dark" : "light"); - const bitIndex = (i % 8) - 8 * Math.floor(i / 8) + 56; - square.id = 'square-' + bitIndex.toString(); - checkForPiece(square, bitIndex); - square.onclick = (e) => { - if (e.ctrlKey) { - const selected = square.classList.contains("selected"); - selectedAction(bitIndex, !selected, output); - if (selected) square.classList.remove("selected"); - else square.classList.add("selected"); - return; - } - - const piece = checkForPiece(square, bitIndex, false); - const sqr_id = parseInt(square.id.slice(7)); - if (hoveringPiece == -1) { - if (piece == null) return; - if (!isYourTurn(piece)) return; - if (validMoves[bitIndex]) renderingMoves = validMoves[bitIndex]; - setHoverpiece(piece); - pickedUpFrom = sqr_id; - square.style.backgroundImage = `none`; - bitboards[piece] &= ~(1n << BigInt(bitIndex)); - } else { - if (sqr_id != pickedUpFrom && !renderingMoves.includes(sqr_id)) return; - renderingMoves = []; - square.style.backgroundImage = `url(${assets[hoveringPiece]})`; - if (piece) bitboards[piece] &= ~(1n << BigInt(bitIndex)); - bitboards[hoveringPiece] |= (1n << BigInt(bitIndex)); - setHoverpiece(-1); - } - console.log(piece, hoveringPiece, square, renderingMoves); - updateRenderingMoves(); - }; - board.appendChild(square); - } - const label = document.createElement("div"); - label.classList.add("horizontal_label"); - board.appendChild(label); - for (let i = 0; i < 8; i++) { - const label = document.createElement("div"); - label.classList.add("horizontal_label"); - label.textContent = ["a", "b", "c", "d", "e", "f", "g", "h"][i]; - board.appendChild(label); - } - - const mouse = document.getElementById("mouse"); - function setHoverpiece(i) { - let oldHoveringPiece = hoveringPiece; - hoveringPiece = i; - if (i < 0) { - mouse.style.backgroundImage = `none`; - checkMoveMade(oldHoveringPiece); - return; - } - mouse.style.backgroundImage = `url(${assets[i]})`; - } - window.onmousemove = (e) => { - const x = e.clientX; - const y = e.clientY; - mouse.style.left = x.toString() + 'px'; - mouse.style.top = y.toString() + 'px'; - } -} diff --git a/assets/pieces/bb.webp b/assets/pieces/bb.webp Binary files differdeleted file mode 100644 index f780b4d..0000000 --- a/assets/pieces/bb.webp +++ /dev/null diff --git a/assets/pieces/bk.webp b/assets/pieces/bk.webp Binary files differdeleted file mode 100644 index 23d2e3b..0000000 --- a/assets/pieces/bk.webp +++ /dev/null diff --git a/assets/pieces/bn.webp b/assets/pieces/bn.webp Binary files differdeleted file mode 100644 index 68a6d63..0000000 --- a/assets/pieces/bn.webp +++ /dev/null diff --git a/assets/pieces/bp.png b/assets/pieces/bp.png Binary files differdeleted file mode 100644 index fa57435..0000000 --- a/assets/pieces/bp.png +++ /dev/null diff --git a/assets/pieces/bq.png b/assets/pieces/bq.png Binary files differdeleted file mode 100644 index 6334dd4..0000000 --- a/assets/pieces/bq.png +++ /dev/null diff --git a/assets/pieces/br.webp b/assets/pieces/br.webp Binary files differdeleted file mode 100644 index 8d078e1..0000000 --- a/assets/pieces/br.webp +++ /dev/null diff --git a/assets/pieces/wb.webp b/assets/pieces/wb.webp Binary files differdeleted file mode 100644 index 5020e5e..0000000 --- a/assets/pieces/wb.webp +++ /dev/null diff --git a/assets/pieces/wk.webp b/assets/pieces/wk.webp Binary files differdeleted file mode 100644 index 72fdcf7..0000000 --- a/assets/pieces/wk.webp +++ /dev/null diff --git a/assets/pieces/wn.png b/assets/pieces/wn.png Binary files differdeleted file mode 100644 index a03ccac..0000000 --- a/assets/pieces/wn.png +++ /dev/null diff --git a/assets/pieces/wp.png b/assets/pieces/wp.png Binary files differdeleted file mode 100644 index d968278..0000000 --- a/assets/pieces/wp.png +++ /dev/null diff --git a/assets/pieces/wq.webp b/assets/pieces/wq.webp Binary files differdeleted file mode 100644 index bfbd57a..0000000 --- a/assets/pieces/wq.webp +++ /dev/null diff --git a/assets/pieces/wr.png b/assets/pieces/wr.png Binary files differdeleted file mode 100644 index 69811d8..0000000 --- a/assets/pieces/wr.png +++ /dev/null @@ -7,15 +7,15 @@ #include <string.h> #define GLOBAL_INCLUDE "-Iinclude/" -#define ENGINE_INCLUDE "-Iinclude/engine" -#define UCI_INCLUDE "-Iinclude/uci" #define CC "gcc", "-fsanitize=address", "-g", GLOBAL_INCLUDE + #define ENGINE_O "output/engine.o" #define UCI_O "output/uci.o" -#define MAIN_O "output/main.o" #define IPC_O "output/ipc.o" +#define MAIN_O "output/main.o" + int status; #define RUN_CMD(...) do { \ @@ -113,8 +113,8 @@ int uci_mode(int run_mode) { } RUN_CMD({CC, "-c", "src/ipc.c", "-o", IPC_O, NULL}); - RUN_CMD({CC, ENGINE_INCLUDE, "-c", "src/engine.c", "-o", ENGINE_O, NULL}); - RUN_CMD({CC, UCI_INCLUDE, "-c", "src/uci.c", "-o", UCI_O, NULL}); - RUN_CMD({CC, UCI_O, ENGINE_O, IPC_O, "-o", MAIN_O, NULL}); + RUN_CMD({CC, "-c", "src/engine.c", "-o", ENGINE_O, NULL}); + RUN_CMD({CC, "-c", "src/uci.c", "-o", UCI_O, NULL}); + RUN_CMD({CC, "src/main.c", UCI_O, ENGINE_O, IPC_O, "-o", MAIN_O, NULL}); return status != 0; } diff --git a/include/engine/moves.h b/include/engine/moves.h index 86c4844..4032557 100644 --- a/include/engine/moves.h +++ b/include/engine/moves.h @@ -1,8 +1,8 @@ #ifndef MOVES_H #define MOVES_H -#include "../ints.h" -#include "../bitboard.h" +#include "ints.h" +#include "bitboard.h" typedef u8 square_t; @@ -10,9 +10,9 @@ typedef u8 square_t; // 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, + 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 @@ -28,10 +28,10 @@ typedef struct { square_t to; u16 flags; } move_t; -void position_make_move(position_t* position, move_t* move); +void position_make_move(position_t *position, move_t *move); typedef struct { - move_t* moves; + move_t *moves; u32 length; u32 capacity; } moves_t; @@ -50,32 +50,34 @@ struct add_move_params { (struct add_move_params) { .flags = 0, __VA_ARGS__ }\ ) void _add_move( - moves_t* moves, + 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_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 get_moves(moves_t *moves, position_t position); +#ifdef MOVES_INTERNAL void __forloop_rook_moves_gen( - moves_t* moves, + moves_t *moves, bitboard_t friendly_type, bitboard_t friendly_pieces, bitboard_t enemy_pieces ); void __forloop_bishop_moves_gen( - moves_t* moves, + moves_t *moves, bitboard_t friendly_type, bitboard_t friendly_pieces, bitboard_t enemy_pieces ); +#endif // MOVES_INTERNAL #endif // !MOVES_H diff --git a/include/engine/threads.h b/include/engine/threads.h new file mode 100644 index 0000000..4815a4c --- /dev/null +++ b/include/engine/threads.h @@ -0,0 +1,53 @@ +#ifndef ENGINE_THREADS_H +#define ENGINE_THREADS_H + +#include <pthread.h> +#include <stdatomic.h> + +#include "bitboard.h" +#include "ipc/engine_message.h" +#include "ipc/go_args.h" + +struct thread_args { + // signal sent by threads manager + atomic_int stop; + + // signal sent by thread + atomic_int finished; + + int id; + position_t *position; + go_args_t *go_args; + engine_message_handler_t *message; +}; + +struct threads { + pthread_t *threads; + struct thread_args *args; + size_t count; + size_t capacity; + + int running_count; + engine_messages_t *engine_messages; + go_args_t *go_args; + position_t *position; +}; + +#ifdef ENGINE_THREADS_INTERNAL +void __threads_args_init( + struct thread_args* args, + struct threads *handler, + int i +); +#endif +void threads_init(struct threads *handler, size_t capacity); +void threads_deinit(struct threads *handler); +void threads_reserve(struct threads *handler, size_t capacity); +void threads_go(struct threads *handler); +bool threads_go_loop(struct threads *handler); +bool threads_all_done(struct threads *handler); +void threads_cleanup(struct threads *handler); + +void *engine_thread(void *args); + +#endif // ENGINE_THREADS_H diff --git a/include/ipc.h b/include/ipc.h deleted file mode 100644 index 90a2bcc..0000000 --- a/include/ipc.h +++ /dev/null @@ -1,78 +0,0 @@ -#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/ipc/engine_message.h b/include/ipc/engine_message.h new file mode 100644 index 0000000..a651bc2 --- /dev/null +++ b/include/ipc/engine_message.h @@ -0,0 +1,67 @@ +#ifndef ENGINE_MESSAGE_H +#define ENGINE_MESSAGE_H + +#include "ipc/moves.h" +#include <stdatomic.h> + +typedef struct engine_message { + atomic_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; + ipc_moves_t pv; + + ipc_move_t best_move; + ipc_move_t ponder; + + struct engine_message *next; +} engine_message_t; + +typedef struct { + engine_message_t *oldest_valid; + engine_message_t *newest_valid; + int count; + + // mainly for debugging purposes + int popped_count; + int pushed_count; + +} engine_message_handler_t; + +typedef struct { + engine_message_handler_t **data; + int count; + int capacity; +} engine_messages_t; + +void engine_message_handler_init(engine_message_handler_t *handle); +void engine_message_handler_acquire(engine_message_handler_t *handle); +void engine_message_handler_release(engine_message_handler_t *handle); +bool engine_message_handler_can_pop(engine_message_handler_t *handle); +engine_message_t *engine_message_handler_pop( + engine_message_handler_t *handle +); +engine_message_t *engine_message_handler_push( + engine_message_handler_t *handle +); + +void engine_messages_init(engine_messages_t *messages); +void engine_messages_deinit(engine_messages_t *messages); + +void engine_message_init(engine_message_t *message); +void engine_messages_refresh(engine_messages_t *messages); +void engine_message_mark_ready(engine_message_t *message); +bool engine_message_is_ready(engine_message_t *message); +void engine_message_deinit(engine_message_t *message); + +#endif // ENGINE_MESSAGE_H diff --git a/include/ipc/go_args.h b/include/ipc/go_args.h new file mode 100644 index 0000000..7121255 --- /dev/null +++ b/include/ipc/go_args.h @@ -0,0 +1,25 @@ +#ifndef GO_ARGS_H +#define GO_ARGS_H + +#include "ipc/moves.h" +#include "ipc/engine_message.h" + +typedef struct { + ipc_moves_t 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; +} go_args_t; + +bool should_continue(engine_message_t *message, go_args_t *go); + +#endif // GO_ARGS_H diff --git a/include/ipc/moves.h b/include/ipc/moves.h new file mode 100644 index 0000000..f08c424 --- /dev/null +++ b/include/ipc/moves.h @@ -0,0 +1,19 @@ +#ifndef IPC_MOVES_H +#define IPC_MOVES_H + +typedef struct { + int from; + int to; +} ipc_move_t; + +typedef struct { + ipc_move_t *data; + int count; + int capacity; +} ipc_moves_t; + +void ipc_moves_init(ipc_moves_t *moves); +void ipc_moves_deinit(ipc_moves_t *moves); +void add_ipc_move(ipc_moves_t *moves, ipc_move_t move); + +#endif // IPC_MOVES_H diff --git a/include/ipc/state.h b/include/ipc/state.h new file mode 100644 index 0000000..6a4455d --- /dev/null +++ b/include/ipc/state.h @@ -0,0 +1,42 @@ +#ifndef IPC_STATE_H +#define IPC_STATE_H + +#include <stdatomic.h> + +#include "bitboard.h" +#include "ipc/moves.h" +#include "ipc/engine_message.h" +#include "uci/state.h" + +enum { + EVENT_INIT, + EVENT_STATE_INITIALISED, + EVENT_UCI_STATE_INITIALISED, + EVENT_UCI_RUNNING, + EVENT_UCI_STOP, + EVENT_UCI_QUIT, + EVENT_ENGINE_GO, + EVENT_ENGINE_RUNNING, + EVENT_ENGINE_STOP, + + EVENTS_COUNT +}; +typedef struct { + atomic_int event; + + engine_messages_t engine_messages; + uci_state_t uci_state; + + // reset on new game + position_t from_position; + ipc_moves_t moves; +} ipc_state_t; + +void ipc_state_init(ipc_state_t *state); +void ipc_state_deinit(ipc_state_t *state); +void ipc_state_game_reset(ipc_state_t *state); +void ipc_state_wait_for_event(ipc_state_t *state, size_t event); +bool ipc_state_is_event(ipc_state_t *state, size_t event); +void ipc_state_set_event(ipc_state_t *state, size_t event); + +#endif // IPC_STATE_H diff --git a/include/ipc/threads.h b/include/ipc/threads.h new file mode 100644 index 0000000..2d76459 --- /dev/null +++ b/include/ipc/threads.h @@ -0,0 +1,9 @@ +#ifndef IPC_THREADS +#define IPC_THREADS + +#include "engine/threads.h" +#include "ipc/state.h" + +void threads_link(struct threads *handler, ipc_state_t *ipc_state); + +#endif // IPC_THREADS diff --git a/include/ipc/uci.h b/include/ipc/uci.h new file mode 100644 index 0000000..cbe98f2 --- /dev/null +++ b/include/ipc/uci.h @@ -0,0 +1,9 @@ +#ifndef UCI_H +#define UCI_H + +#include "ipc/state.h" + +void *uci(ipc_state_t *state); +void handle_ipc(ipc_state_t *state); + +#endif // UCI_H diff --git a/include/uci.h b/include/uci.h deleted file mode 100644 index b3ee4cc..0000000 --- a/include/uci.h +++ /dev/null @@ -1,8 +0,0 @@ -#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 deleted file mode 100644 index ba9c51d..0000000 --- a/include/uci/command.h +++ /dev/null @@ -1,21 +0,0 @@ -#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/internals/command.h b/include/uci/internals/command.h new file mode 100644 index 0000000..2994b04 --- /dev/null +++ b/include/uci/internals/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; +} uci_cmd_t; + +uci_cmd_t uci_cmd_init(); +void uci_cmd_add(uci_cmd_t *cmd, const char *token); +void uci_cmd_set_root(uci_cmd_t *cmd, const char *token); +void uci_cmd_append_arg(uci_cmd_t *cmd, const char *token); +char *uci_cmd_get_arg(uci_cmd_t cmd, int i); +void uci_cmd_deinit(uci_cmd_t cmd); + +#endif // UCI_COMMAND_H diff --git a/include/uci/internals/response.h b/include/uci/internals/response.h new file mode 100644 index 0000000..a0a6e99 --- /dev/null +++ b/include/uci/internals/response.h @@ -0,0 +1,24 @@ +#ifndef UCI_RESPONSE_H +#define UCI_RESPONSE_H + +#include "uci/internals/command.h" +#include "uci/state.h" + +enum { + UCI_STATE_INITIAL, + UCI_STATE_IDLE, + UCI_STATE_SYNC, + UCI_STATE_PING, + UCI_STATE_ACTIVE, + UCI_STATE_HALT, +}; + +void handle_uci(uci_state_t *state, uci_cmd_t cmd); +void handle_initial(uci_state_t *state, uci_cmd_t cmd); +void handle_idle(uci_state_t *state, uci_cmd_t cmd); +void handle_sync(uci_state_t *state, uci_cmd_t cmd); +void handle_ping(uci_state_t *state, uci_cmd_t cmd); +void handle_active(uci_state_t *state, uci_cmd_t cmd); +void handle_halt(uci_state_t *state, uci_cmd_t cmd); + +#endif // UCI_RESPONSE_H diff --git a/include/uci/response.h b/include/uci/response.h deleted file mode 100644 index 320b1f0..0000000 --- a/include/uci/response.h +++ /dev/null @@ -1,24 +0,0 @@ -#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 index a1df891..51207f3 100644 --- a/include/uci/state.h +++ b/include/uci/state.h @@ -1,11 +1,12 @@ #ifndef UCI_STATE_H #define UCI_STATE_H -#include <stdatomic.h> -#include "../fen.h" +#include "ipc/go_args.h" +#include "ipc/moves.h" +#include "bitboard.h" typedef struct { - char* data; + char *data; int length; } str_t; @@ -19,7 +20,7 @@ typedef int combo_t; typedef bool button_t; typedef struct { - char** combination; + char **combination; int count; int default_index; } option_combo_setting_t; @@ -36,7 +37,7 @@ typedef struct { option_combo_setting_t combo; option_spin_setting_t spin; bool check_default; - const char* string_default; + const char *string_default; } data; union { combo_t *combo; @@ -47,52 +48,63 @@ typedef struct { } value; } option_setting_t; -option_setting_t option_setting_combo( - char* option_name, - char** combinations, +void option_setting_combo( + option_setting_t *target, + char *option_name, + char **combinations, int combinations_count, int default_index, combo_t *combo ); -option_setting_t option_setting_spin( - const char* option_name, +void option_setting_spin( + option_setting_t *target, + const char *option_name, int min, int max, int default_value, spin_t *spin ); -option_setting_t option_setting_check( - const char* option_name, +void option_setting_check( + option_setting_t *target, + const char *option_name, bool default_value, check_t *check ); -option_setting_t option_setting_string( - const char* option_name, - const char* default_value, +void option_setting_string( + option_setting_t *target, + const char *option_name, + const char *default_value, str_t *string ); -option_setting_t option_setting_button( - const char* option_name, +void option_setting_button( + option_setting_t *target, + const char *option_name, button_t *button ); +void print_setting(option_setting_t setting); + +enum { + UCI_SIGNAL_NONE, + UCI_SIGNAL_QUIT, + UCI_SIGNAL_GO, + UCI_SIGNAL_GO_LOOP, + UCI_SIGNAL_STOP, // game stop, don't stop the program + + UCI_SIGNAL_COUNT +}; typedef struct { + size_t signal; + size_t current_state; + 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 + go_args_t go_args; position_t position; - struct uci_move *moves; - int moves_count; - - option_setting_t option_settings[11]; + ipc_moves_t *moves; +option_setting_t option_settings[11]; // options spin_t threads; @@ -112,11 +124,10 @@ typedef struct { str_t uci_engineabout; // str_t uci_shredderbasespath; str_t uci_setpositionvalue; -} uci_state; +} uci_state_t; -struct uci_move { - int from; - int to; -}; +void uci_state_init(uci_state_t *state); +void uci_state_deinit(uci_state_t *state); +void apply_option(uci_state_t *state, char *name, char *buffer); #endif // UCI_STATE_H diff --git a/justfile b/justfile new file mode 100644 index 0000000..5892885 --- /dev/null +++ b/justfile @@ -0,0 +1,7 @@ +dev: + ./build uci + ./build uci run + +analysis: + python symbol_analyzer/main.py + xdg-open symbol_analyzer/index.html diff --git a/src/bitboard.c b/src/bitboard.c index 565f425..9df3855 100644 --- a/src/bitboard.c +++ b/src/bitboard.c @@ -1,6 +1,6 @@ #include "bitboard.h" + #include <stdio.h> -#include <inttypes.h> #include <assert.h> position_t position_starting() { diff --git a/src/engine.c b/src/engine.c index dc1f54e..a656a79 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1,199 +1,3 @@ -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <pthread.h> -#include "fcntl.h" - -#include "bitboard.h" -#include "moves.h" -#include "fen.h" -#include "uci.h" -#include "ipc.h" - -struct thread_args { - int id; - int stop; - position_t position; - struct go_args *go_args; - struct engine_message *message; -}; - -void *engine_thread(void *_args) { - printf("NIGGGGA\n"); - struct thread_args *args = (struct thread_args*)_args; - args->stop = 0; - - int depth = 0; - while (true) { - struct engine_message *message = args->message; - message->depth = depth++; - message->multipv = args->id; - message->pv = comm_moves_init(); - - // pseudo engine work - for (volatile int k = 0; k < 1000000000; k++) {} - - add_comm_move(&message->pv, (struct uci_move) { 14, 24 }); - - if (args->stop || !should_continue(message, args->go_args)) { - message->best_move = (struct uci_move) { 12, 24 }; - message->ponder = (struct uci_move) { 42, 54 }; - message->next = NULL; - message->ready = 1; - break; - } - - message->next = malloc(sizeof(struct engine_message*)); - message->next->ready = 0; - message->ready = 1; - args->message = message->next; - } - - args->stop = 2; -} - -struct threads { - pthread_t *threads; - struct thread_args* args; - struct go_args *go_args; - engine_messages *engine_messages; - size_t count; - size_t capacity; - - position_t sharing_position; -}; - -void increase_threads(struct threads *threads, size_t change) { - int old_capacity = threads->capacity; - if (threads->count + change > threads->capacity) { - threads->capacity = threads->count + change + 16; - } - - threads->threads = threads->threads == NULL - ? malloc(sizeof(pthread_t) * threads->capacity) - : realloc(threads->threads, sizeof(pthread_t) * threads->capacity); - - threads->args = threads->args == NULL - ? malloc(sizeof(struct thread_args) * threads->capacity) - : realloc(threads->args, sizeof(struct thread_args) * threads->capacity); - - threads->engine_messages->data = threads->engine_messages->data == NULL - ? malloc(sizeof(struct engine_message*) * threads->capacity) - : realloc( - threads->engine_messages->data, - sizeof(struct engine_message*) * threads->capacity - ); - - for (int i = threads->count; i < threads->count + change; i++) { - threads->engine_messages->data[i] = malloc(sizeof(struct engine_message)); - threads->engine_messages->data[i]->ready = 0; - threads->args[i] = (struct thread_args) { - i, - 0, - threads->sharing_position, - threads->go_args, - threads->engine_messages->data[i], - }; - pthread_create( - threads->threads + i, - NULL, - &engine_thread, - (void*)(threads->args + i) - ); - } - threads->count += change; - threads->engine_messages->count = threads->count; -} - -void decrease_threads(struct threads *threads, size_t change) { - for (int i = 0; i < change; i++) { - struct engine_message *item = threads->engine_messages->data[i]; - threads->engine_messages->data[i] = NULL; - free(item); - pthread_cancel(threads->threads[threads->count - i - 1]); - } - threads->count -= change; - threads->engine_messages->count = threads->count; -} - -void set_threads(struct threads *threads, size_t new_size) { - if (new_size >= threads->count) { - increase_threads(threads, new_size - threads->count); - } else { - decrease_threads(threads, threads->count - new_size); - } -} - -void send_stop_signal(struct threads *threads) { - for (int i = 0; i < threads->count; i++) { - if (threads->args[i].stop) continue; - threads->args[i].stop = 1; - } -} -bool all_stopped(struct threads *threads) { - if (threads->count == 0) return false; - for (int i = 0; i < threads->count; i++) { - if (threads->args[i].stop == 2) continue; - return false; - } - return true; -} - -// TODO: someday fix that some structs have typedef, some dont -int main(int argc, char** argv) { - comms *comms = malloc(sizeof(*comms)); - comms->engine_messages = malloc(sizeof(*comms->engine_messages)); - comms->engine_messages->data = NULL; - comms->uci_state_initialized = 0; - - pthread_t uci_thread; - pthread_create(&uci_thread, NULL, &uci, (void*)comms); - - while (atomic_load(&comms->uci_state_initialized) == 0); - comms->state.quit = 0; - - struct threads engine_threads = {0}; - engine_threads.engine_messages = comms->engine_messages; - - while (1) { - if (atomic_load(&comms->state.quit)) break; - if (atomic_load(&comms->state.cleanup)) { - set_threads(&engine_threads, 0); - for (int i = 0; i < engine_threads.count; i++) { - engine_threads.args[i].stop = -1; - } - } - if (atomic_load(&comms->state.go)) { - printf("going\n"); - engine_threads.sharing_position = comms->state.position; - engine_threads.go_args = (struct go_args*)comms->state.go_args; - set_threads(&engine_threads, comms->state.threads); - atomic_store(&comms->state.go, 0); - atomic_store(&comms->state.go_ready_receive, 1); - } - if (atomic_load(&comms->state.stop)) { - printf("stopping\n"); - send_stop_signal(&engine_threads); - if (!all_stopped(&engine_threads)) continue; - set_threads(&engine_threads, 0); - for (int i = 0; i < engine_threads.count; i++) { - engine_threads.args[i].stop = -1; - } - atomic_store(&comms->state.stop, 0); - } - } - - pthread_cancel(uci_thread); - set_threads(&engine_threads, 0); - free(engine_threads.threads); - free(engine_threads.args); - for (int i = 0; i < engine_threads.count; i++) { - free(engine_threads.engine_messages->data[i]); - } - free(comms->engine_messages->data); - free(comms->engine_messages); - free(comms); - return 0; -} - +#include "engine/threads.c" +#include "engine/thread.c" #include "engine/moves.c" diff --git a/src/engine/moves.c b/src/engine/moves.c index 56bb47d..05278a5 100644 --- a/src/engine/moves.c +++ b/src/engine/moves.c @@ -1,4 +1,4 @@ -#include "moves.h" +#include "engine/moves.h" #include "bitboard.h" #include "moves/vec.c" diff --git a/src/engine/moves/bishop.c b/src/engine/moves/bishop.c index b69be57..0bc47f8 100644 --- a/src/engine/moves/bishop.c +++ b/src/engine/moves/bishop.c @@ -1,4 +1,5 @@ -#include "moves.h" +#define MOVES_INTERNAL +#include "engine/moves.h" void __forloop_bishop_moves_gen( moves_t* moves, diff --git a/src/engine/moves/king.c b/src/engine/moves/king.c index 1775e7f..706cf9c 100644 --- a/src/engine/moves/king.c +++ b/src/engine/moves/king.c @@ -1,8 +1,8 @@ -#include "moves.h" -#include <stdio.h> +#define MOVES_INTERNAL +#include "engine/moves.h" void get_king_moves(moves_t* moves, position_t position) { - // assert_valid_position(position); + assert_valid_position(position); bitboard_t friendly_king; int king_square; diff --git a/src/engine/moves/knight.c b/src/engine/moves/knight.c index e7615f0..64e44ed 100644 --- a/src/engine/moves/knight.c +++ b/src/engine/moves/knight.c @@ -1,4 +1,5 @@ -#include "moves.h" +#define MOVES_INTERNAL +#include "engine/moves.h" bitboard_t knight_moves[64] = { 132096ULL, diff --git a/src/engine/moves/pawn.c b/src/engine/moves/pawn.c index d9757f4..66b1d06 100644 --- a/src/engine/moves/pawn.c +++ b/src/engine/moves/pawn.c @@ -1,4 +1,5 @@ -#include "moves.h" +#define MOVES_INTERNAL +#include "engine/moves.h" #define add_promote_moves(other_flags) \ add_move(moves, from, to, .flags = other_flags | MOVE_PROMOTE_Q); \ diff --git a/src/engine/moves/queen.c b/src/engine/moves/queen.c index bdf96fc..3e0b8ef 100644 --- a/src/engine/moves/queen.c +++ b/src/engine/moves/queen.c @@ -1,4 +1,5 @@ -#include "moves.h" +#define MOVES_INTERNAL +#include "engine/moves.h" void get_queen_moves(moves_t* moves, position_t position) { assert_valid_position(position); diff --git a/src/engine/moves/rook.c b/src/engine/moves/rook.c index 3e0ac95..abbc784 100644 --- a/src/engine/moves/rook.c +++ b/src/engine/moves/rook.c @@ -1,4 +1,5 @@ -#include "moves.h" +#define MOVES_INTERNAL +#include "engine/moves.h" void __forloop_rook_moves_gen( moves_t* moves, diff --git a/src/engine/moves/vec.c b/src/engine/moves/vec.c index 9ded70d..b5cbb6f 100644 --- a/src/engine/moves/vec.c +++ b/src/engine/moves/vec.c @@ -1,4 +1,5 @@ -#include "moves.h" +#include "engine/moves.h" + #include <assert.h> #include <stdlib.h> diff --git a/src/engine/thread.c b/src/engine/thread.c new file mode 100644 index 0000000..017e9b6 --- /dev/null +++ b/src/engine/thread.c @@ -0,0 +1,34 @@ +#include "engine/threads.h" +#include <stdio.h> + +void *engine_thread(void *_args) { + struct thread_args *args = (struct thread_args*)_args; + args->stop = 0; + + int depth = 0; + engine_message_t *message = args->message->newest_valid; + while (true) { + message->depth = depth++; + message->multipv = args->id; + ipc_moves_init(&message->pv); + + // pseudo engine work + for (volatile int k = 0; k < 1000000000; k++) {} + + add_ipc_move(&message->pv, (ipc_move_t) { 14, 24 }); + + if (args->stop || !should_continue(message, args->go_args)) { + message->best_move = (ipc_move_t) { 12, 24 }; + message->ponder = (ipc_move_t) { 42, 54 }; + message->next = NULL; + engine_message_mark_ready(message); + break; + } + + engine_message_mark_ready(message); + message = engine_message_handler_push(args->message); + } + + args->stop = 2; +} + diff --git a/src/engine/threads.c b/src/engine/threads.c new file mode 100644 index 0000000..5afe155 --- /dev/null +++ b/src/engine/threads.c @@ -0,0 +1,91 @@ +#define ENGINE_THREADS_INTERNAL +#include "engine/threads.h" +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include <stdio.h> + +void threads_init(struct threads *handler, size_t capacity) { + // maybe this will be a speed up? + // why am i micro optimizing here?????? + // idk i just watched the eskil steenberg video about UB + memset(handler, 0, sizeof(*handler)); + + handler->threads = malloc(sizeof(*handler->threads) * capacity); + handler->args = malloc(sizeof(*handler->args) * capacity); + handler->capacity = capacity; + handler->count = 0; + handler->running_count = 0; + handler->engine_messages = NULL; + handler->go_args = NULL; + handler->position = NULL; +} + +void threads_deinit(struct threads *handler) { + assert(handler->running_count == 0); + free(handler->threads); + free(handler->args); +} + +void threads_reserve(struct threads *handler, size_t capacity) { + if (handler->capacity >= capacity) return; + + handler->threads = realloc( + handler->threads, + sizeof(*handler->threads) * capacity + ); + handler->args = realloc( + handler->args, + sizeof(*handler->args) * capacity + ); + handler->capacity = capacity; +} + +void threads_go(struct threads *handler) { + int running_count = handler->running_count; + for (int i = 0; i < running_count; i++) { + __threads_args_init(handler->args + i, handler, i); + pthread_create( + handler->threads + i, + NULL, + engine_thread, + handler->args + i + ); + } +} + +bool threads_go_loop(struct threads *handler) { + // idk maybe do something while waiting for calculations to flow in +} + +bool threads_all_done(struct threads *handler) { + int running_count = handler->running_count; + assert(running_count > 0); + for (int i = 0; i < running_count; i++) { + if (atomic_load(&handler->args[i].finished) == 1) continue; + return false; + } + return true; +} + +void threads_cleanup(struct threads *handler) { + int running_count = handler->running_count; + for (int i = 0; i < running_count; i++) { + __threads_args_init(handler->args + i, handler, i); + pthread_cancel(handler->threads[i]); + } + handler->running_count = 0; +} + +void __threads_args_init( + struct thread_args* args, + struct threads *handler, + int i +) { + atomic_init(&args->stop, 0); + atomic_init(&args->finished, 0); + args->id = i; + args->position = handler->position; + args->go_args = handler->go_args; + args->message = handler->engine_messages->data[i]; +} @@ -1,4 +1,3 @@ -#include <assert.h> #include <stdbool.h> #include "fen.h" @@ -1,46 +1,5 @@ -#ifndef IPC_C -#define IPC_C - -#include "ipc.h" - -comm_moves comm_moves_init() { - return (comm_moves) { - malloc(sizeof(struct uci_move) * 50), - 0, - 50 - }; -} - -void add_comm_move(comm_moves *moves, struct uci_move move) { - if (moves->count + 1 > moves->capacity) { - moves->capacity += 50; - moves->moves = realloc( - moves->moves, - moves->capacity * sizeof(struct uci_move) - ); - } - moves->moves[moves->count++] = move; -} - - -bool should_continue(struct engine_message *message, struct go_args* go) { - int depth; - int nodes; - int mate; - if (go->depth && (go->depth >= message->depth)) { - return false; - } - if (go->nodes && (go->nodes >= message->nodes)) { - message->node_limit = true; - return false; - } - if (go->mate && message->mate && (go->mate <= message->mate)) { - return false; - } - return true; -} - -#include "fen.c" -#include "bitboard.c" - -#endif // IPC_C +#include "ipc/go_args.c" +#include "ipc/moves.c" +#include "ipc/engine_message.c" +#include "ipc/state.c" +#include "ipc/threads.c" diff --git a/src/ipc/engine_message.c b/src/ipc/engine_message.c new file mode 100644 index 0000000..76814f4 --- /dev/null +++ b/src/ipc/engine_message.c @@ -0,0 +1,127 @@ +#include "ipc/engine_message.h" +#include <stdio.h> +#include <assert.h> + +atomic_flag handler_busy; + +void engine_message_handler_init(engine_message_handler_t *handle) { + engine_message_t *message = calloc(sizeof(*message), 1); + + engine_message_init(message); + + handle->oldest_valid = message; + handle->newest_valid = message; + handle->count = 1; + handle->pushed_count = 0; + handle->popped_count = 0; +} + +void engine_message_handler_acquire(engine_message_handler_t *handle) { + while (atomic_flag_test_and_set(&handler_busy)); +} + +void engine_message_handler_release(engine_message_handler_t *handle) { + atomic_flag_clear(&handler_busy); +} + +bool engine_message_handler_can_pop(engine_message_handler_t *handle) { + assert(handle != NULL); + engine_message_handler_acquire(handle); + if (handle->count == 0) { + engine_message_handler_release(handle); + return false; + } + if (handle->oldest_valid == NULL) { + printf("%d\n", handle->count); + } + bool output = engine_message_is_ready(handle->oldest_valid); + engine_message_handler_release(handle); + return output; +} + +engine_message_t *engine_message_handler_pop( + engine_message_handler_t *handle +) { + assert(handle != NULL); + engine_message_handler_acquire(handle); + + engine_message_t *output = handle->oldest_valid; + + handle->oldest_valid = handle->oldest_valid->next; + handle->count--; + handle->popped_count++; + + engine_message_handler_release(handle); + return output; +} + +engine_message_t *engine_message_handler_push( + engine_message_handler_t *handle +) { + assert(handle != NULL); + engine_message_t *output = calloc(sizeof(*output), 1); + engine_message_init(output); + + engine_message_handler_acquire(handle); + + if (handle->count > 0) { + handle->newest_valid->next = output; + } + handle->newest_valid = output; + if (handle->count == 0) { + handle->oldest_valid = output; + } + handle->count++; + handle->pushed_count++; + + engine_message_handler_release(handle); + + return output; + +} +void engine_messages_init(engine_messages_t *messages) { + assert(messages != NULL); + // idc, i don't want to exceed 10 threads anyway + messages->data = calloc(sizeof(*messages->data), 10); + for (int i = 0; i < 10; i++) { + messages->data[i] = malloc(sizeof(*messages->data[i])); + engine_message_handler_init(messages->data[i]); + } + messages->count = 0; + messages->capacity = 10; +} + +void engine_messages_refresh(engine_messages_t *messages) { + assert(messages != NULL); + for (int i = 0; i < 10; i++) { + messages->data[i] = malloc(sizeof(*messages->data[i])); + engine_message_handler_init(messages->data[i]); + } + messages->count = 0; + messages->capacity = 10; +} + +void engine_message_mark_ready(engine_message_t *message) { + atomic_store(&message->ready, 1); +} + +bool engine_message_is_ready(engine_message_t *message) { + return atomic_load(&message->ready) == 1; +} + +void engine_messages_deinit(engine_messages_t *messages) { + assert(messages != NULL); + free(messages->data); +} + +void engine_message_init(engine_message_t *message) { + assert(message != NULL); + message->ready = 0; + ipc_moves_init(&message->pv); +} + +void engine_message_deinit(engine_message_t *message) { + assert(message != NULL); + ipc_moves_deinit(&message->pv); + free(message); +} diff --git a/src/ipc/go_args.c b/src/ipc/go_args.c new file mode 100644 index 0000000..50f4b72 --- /dev/null +++ b/src/ipc/go_args.c @@ -0,0 +1,19 @@ +#include "ipc/go_args.h" +#include <stdio.h> + +bool should_continue(engine_message_t *message, go_args_t *go) { + int depth; + int nodes; + int mate; + if (go->depth && (go->depth <= message->depth)) { + return false; + } + if (go->nodes && (go->nodes <= message->nodes)) { + message->node_limit = true; + return false; + } + if (go->mate && message->mate && (go->mate >= message->mate)) { + return false; + } + return true; +} diff --git a/src/ipc/moves.c b/src/ipc/moves.c new file mode 100644 index 0000000..acd7085 --- /dev/null +++ b/src/ipc/moves.c @@ -0,0 +1,23 @@ +#include "ipc/moves.h" +#include <stdlib.h> + +void ipc_moves_init(ipc_moves_t *moves) { + moves->data = malloc(sizeof(ipc_move_t) * 50); + moves->count = 0; + moves->capacity = 50; +} + +void ipc_moves_deinit(ipc_moves_t *moves) { + free(moves->data); +} + +void add_ipc_move(ipc_moves_t *moves, ipc_move_t move) { + if (moves->count + 1 > moves->capacity) { + moves->capacity += 50; + moves->data = realloc( + moves->data, + moves->capacity * sizeof(ipc_move_t) + ); + } + moves->data[moves->count++] = move; +} diff --git a/src/ipc/state.c b/src/ipc/state.c new file mode 100644 index 0000000..02ba38b --- /dev/null +++ b/src/ipc/state.c @@ -0,0 +1,41 @@ +#include <string.h> +#include <assert.h> + +#define IPC_INTERNAL +#include "ipc/state.h" + +void ipc_state_init(ipc_state_t *state) { + // done by main.c in the loop + // engine_messages_init(&state->engine_messages); + uci_state_init(&state->uci_state); + state->from_position = (position_t) {0}; + ipc_moves_init(&state->moves); + state->uci_state.moves = &state->moves; + atomic_init(&state->event, EVENT_INIT); +} + +void ipc_state_deinit(ipc_state_t *state) { + engine_messages_deinit(&state->engine_messages); + uci_state_deinit(&state->uci_state); + ipc_moves_deinit(&state->moves); +} + +void ipc_state_game_reset(ipc_state_t *state) { + state->from_position = (position_t) {0}; + state->moves.count = 0; +} + +void ipc_state_wait_for_event(ipc_state_t *state, size_t event) { + assert(event < EVENTS_COUNT); + while (!ipc_state_is_event(state, event)); +} + +bool ipc_state_is_event(ipc_state_t *state, size_t event) { + assert(event < EVENTS_COUNT); + return atomic_load(&state->event) == event; +} + +void ipc_state_set_event(ipc_state_t *state, size_t event) { + assert(event < EVENTS_COUNT); + atomic_store(&state->event, event); +} diff --git a/src/ipc/threads.c b/src/ipc/threads.c new file mode 100644 index 0000000..9ed04de --- /dev/null +++ b/src/ipc/threads.c @@ -0,0 +1,8 @@ +#include "ipc/threads.h" + +void threads_link(struct threads *handler, ipc_state_t *ipc_state) { + handler->engine_messages = &ipc_state->engine_messages; + handler->go_args = &ipc_state->uci_state.go_args; + handler->position = &ipc_state->uci_state.position; +} + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d71585b --- /dev/null +++ b/src/main.c @@ -0,0 +1,90 @@ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include "fcntl.h" + +#include "ipc/state.h" +#include "ipc/threads.h" +#include "ipc/uci.h" + +void *uci_thread_func(void* data) { + ipc_state_t *state = (ipc_state_t*)data; + return uci(state); +} + +int main(int argc, char** argv) { + ipc_state_t ipc_state; + ipc_state_init(&ipc_state); + + pthread_t uci_thread; + pthread_create(&uci_thread, NULL, uci_thread_func, (void*)&ipc_state); + + struct threads engine_threads = {0}; + threads_init(&engine_threads, ipc_state.uci_state.threads); + threads_link(&engine_threads, &ipc_state); + + engine_messages_init(&ipc_state.engine_messages); + goto skip_refresh; +waiting_for_go: + engine_messages_refresh(&ipc_state.engine_messages); +skip_refresh: + ipc_state_wait_for_event(&ipc_state, EVENT_ENGINE_GO); + + engine_threads.running_count = ipc_state.uci_state.threads; + ipc_state.engine_messages.count = ipc_state.uci_state.threads; + threads_reserve(&engine_threads, ipc_state.uci_state.threads); + threads_go(&engine_threads); + + ipc_state_set_event(&ipc_state, EVENT_UCI_RUNNING); + + bool is_stop; + while (1) { + while ( + !ipc_state_is_event(&ipc_state, EVENT_ENGINE_RUNNING) && + !(is_stop = ipc_state_is_event(&ipc_state, EVENT_ENGINE_STOP)) + ); + if (is_stop) { + printf("ENDED\n"); + threads_cleanup(&engine_threads); + ipc_state_set_event(&ipc_state, EVENT_UCI_RUNNING); + goto waiting_for_go; + } + threads_go_loop(&engine_threads); + ipc_state_set_event(&ipc_state, EVENT_UCI_RUNNING); + // if (atomic_load(&ipc_state->state.quit)) break; + // if (atomic_load(&ipc_state->state.cleanup)) { + // set_threads(&engine_threads, 0); + // for (int i = 0; i < engine_threads.count; i++) { + // engine_threads.args[i].stop = -1; + // } + // } + // if (atomic_load(&ipc_state->state.go)) { + // printf("going\n"); + // engine_threads.sharing_position = ipc_state->state.position; + // engine_threads.go_args = (struct go_args*)ipc_state->state.go_args; + // set_threads(&engine_threads, ipc_state->state.threads); + // atomic_store(&ipc_state->state.go, 0); + // atomic_store(&ipc_state->state.go_ready_receive, 1); + // } + // if (atomic_load(&ipc_state->state.stop)) { + // printf("stopping\n"); + // send_stop_signal(&engine_threads); + // if (!all_stopped(&engine_threads)) continue; + // set_threads(&engine_threads, 0); + // for (int i = 0; i < engine_threads.count; i++) { + // engine_threads.args[i].stop = -1; + // } + // atomic_store(&ipc_state->state.stop, 0); + // } + } + + ipc_state_deinit(&ipc_state); + pthread_cancel(uci_thread); + threads_deinit(&engine_threads); + return 0; +} + +#include "fen.c" +#include "bitboard.c" @@ -1,18 +1,17 @@ -#include <stdio.h> #include <string.h> -#include <stdbool.h> #include <fcntl.h> #include <unistd.h> #include <assert.h> +#include <stdio.h> +#include <stdatomic.h> -#include <stdlib.h> -#include "state.h" -#include "command.h" -#include "response.h" -#include "uci.h" -#include "ipc.h" +#include "uci/internals/command.h" +#include "uci/internals/response.h" +#include "uci/state.h" +#include "ipc/state.h" +#include "ipc/uci.h" -void load_from_message(ucicmd* cmd, const char* message) { +void load_from_message(uci_cmd_t* cmd, const char* message) { char token[MAX_TOKEN_SIZE]; int i = 0, k = 0; @@ -27,79 +26,18 @@ void load_from_message(ucicmd* cmd, const char* message) { } i++; token[k] = 0; - ucicmd_add(cmd, token); + uci_cmd_add(cmd, token); k = 0; } token[k] = 0; - ucicmd_add(cmd, token); + uci_cmd_add(cmd, token); } -void *uci(void *_com) { - comms *com = (comms*)_com; +void *uci(ipc_state_t *ipc_state) { // https://stackoverflow.com/a/41559081 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); - com->state = (uci_state) {0}; - strncpy(com->state.name, "Gacrux", 32); - strncpy(com->state.author, "Aargh Rai <aarghrai.com>", 32); - int k = 0; - com->state.option_settings[k++] = option_setting_spin( - "Threads", - 1, 5, 1, - &com->state.threads - ); - com->state.option_settings[k++] = option_setting_spin( - "Hash", - 0, 512, 256, - &com->state.hash - ); - com->state.option_settings[k++] = option_setting_button( - "Clear Hash", - &com->state.clear_hash - ); - com->state.option_settings[k++] = option_setting_check( - "UCI_ShowCurrLine", - false, - &com->state.uci_showcurrline - ); - com->state.option_settings[k++] = option_setting_check( - "UCI_ShowRefutations", - false, - &com->state.uci_showrefutations - ); - com->state.option_settings[k++] = option_setting_check( - "UCI_LimitStrength", - false, - &com->state.uci_limitstrength - ); - com->state.option_settings[k++] = option_setting_spin( - "UCI_Elo", - 100, 3500, 800, - &com->state.uci_elo - ); - com->state.option_settings[k++] = option_setting_check( - "UCI_AnalyseMode", - false, - &com->state.uci_analysemode - ); - com->state.option_settings[k++] = option_setting_string( - "UCI_Opponent", - "<empty>", - &com->state.uci_opponent - ); - com->state.option_settings[k++] = option_setting_string( - "UCI_EngineAbout", - "Gacrux by Aargh Rai, Checkout https://git.aarghrai.com/gacrux", - &com->state.uci_engineabout - ); - com->state.option_settings[k++] = option_setting_string( - "UCI_SetPositionValue", - "<empty>", - &com->state.uci_setpositionvalue - ); - atomic_store(&com->uci_state_initialized, 1); - - ucicmd cmd = ucicmd_init(); + uci_cmd_t cmd = uci_cmd_init(); size_t n; char buf[1024]; @@ -110,11 +48,111 @@ void *uci(void *_com) { if (n > 0) { load_from_message(&cmd, buf); } - handle_uci( - &com->state, - com->engine_messages, - cmd - ); + handle_uci(&ipc_state->uci_state, cmd); + handle_ipc(ipc_state); + } +} + +int k =0; +void handle_ipc(ipc_state_t *state) { + int signal = state->uci_state.signal; + assert(signal < UCI_SIGNAL_COUNT); + if (signal == UCI_SIGNAL_NONE) return; + if (signal == UCI_SIGNAL_QUIT) { + return; + } + if (signal == UCI_SIGNAL_GO) { + // some init stuff + ipc_state_set_event(state, EVENT_ENGINE_GO); + state->uci_state.signal = UCI_SIGNAL_GO_LOOP; + } + if ( + signal == UCI_SIGNAL_GO_LOOP && + ipc_state_is_event(state, EVENT_UCI_RUNNING) + ) { + bool ended = false; + engine_messages_t engine_messages = state->engine_messages; + int engine_messages_count = engine_messages.count; + for (int i = 0; i < engine_messages_count; i++) { + engine_message_handler_t *handler = engine_messages.data[i]; + if (!engine_message_handler_can_pop(handler)) continue; + engine_message_t *message = engine_message_handler_pop(handler); + + printf( + "info depth %d seldepth %d multipv %d ", + message->depth, + message->seldepth, + message->multipv + ); + if (message->mate) { + printf("mate %d ", message->mate); + } else { + printf("score cp %d ", message->score_cp); + } + if (message->node_limit) { + printf("upperbound "); + } + printf( + "nodes %d nps %d hashfull %d tbhits %d time %d pv", + message->nodes, + message->nps, + message->hashfull, + message->tbhits, + message->time + ); + + for (int j = 0; j < message->pv.count; j++) { + ipc_move_t move = message->pv.data[i]; + printf( + " %c%c%c%c", + (move.from / 8) + 'a', + (move.from % 8) + '1', + (move.to / 8) + 'a', + (move.to % 8) + '1' + ); + } + printf("\n"); + + if (message->best_move.from != 0 && message->best_move.to != 0) { + ended = true; + printf( + "bestmove %c%c%c%c", + (message->best_move.from / 8) + 'a', + (message->best_move.from % 8) + '1', + (message->best_move.to / 8) + 'a', + (message->best_move.to % 8) + '1' + ); + if (message->ponder.from != 0 && message->ponder.to != 0) { + printf( + " ponder %c%c%c%c", + (message->ponder.from / 8) + 'a', + (message->ponder.from % 8) + '1', + (message->ponder.to / 8) + 'a', + (message->ponder.to % 8) + '1' + ); + } + printf("\n"); + } + + engine_message_deinit(message); + if (ended) { + state->uci_state.signal = UCI_SIGNAL_NONE; + state->uci_state.current_state = UCI_STATE_IDLE; + break; + } + } + + if (ended) { + ipc_state_set_event(state, EVENT_ENGINE_STOP); + } else { + ipc_state_set_event(state, EVENT_ENGINE_RUNNING); + } + + return; + } + if (signal == UCI_SIGNAL_STOP) { + printf("uci stopping\n"); + return; } } diff --git a/src/uci/command.c b/src/uci/command.c index 02d6e0f..c64fee2 100644 --- a/src/uci/command.c +++ b/src/uci/command.c @@ -1,10 +1,10 @@ #include <assert.h> #include <string.h> #include <stdlib.h> -#include "command.h" +#include "uci/internals/command.h" -ucicmd ucicmd_init() { - ucicmd output = {0}; +uci_cmd_t uci_cmd_init() { + uci_cmd_t output = {0}; output.empty = true; output.args_capacity = 32; @@ -37,16 +37,16 @@ bool is_valid_cmd(const char *token) { (strcmp(token, "option") == 0); } -void ucicmd_add(ucicmd* cmd, const char* token) { +void uci_cmd_add(uci_cmd_t* cmd, const char* token) { if (!cmd->empty) { - ucicmd_append_arg(cmd, token); + uci_cmd_append_arg(cmd, token); return; } if (is_valid_cmd(token) == 0) return; - ucicmd_set_root(cmd, token); + uci_cmd_set_root(cmd, token); } -void ucicmd_set_root(ucicmd* cmd, const char* token) { +void uci_cmd_set_root(uci_cmd_t* cmd, const char* token) { cmd->empty = false; int i = 0; for (; token[i] != 0; i++) { @@ -56,7 +56,7 @@ void ucicmd_set_root(ucicmd* cmd, const char* token) { if (i < MAX_TOKEN_SIZE) cmd->root[i] = 0; } -void ucicmd_append_arg(ucicmd* cmd, const char* token) { +void uci_cmd_append_arg(uci_cmd_t* cmd, const char* token) { if (cmd->args_count + 1 > cmd->args_capacity) { cmd->args_capacity += 32; // does realloc set all zeros, like calloc??? @@ -66,7 +66,7 @@ void ucicmd_append_arg(ucicmd* cmd, const char* token) { sizeof(char) * MAX_TOKEN_SIZE * cmd->args_capacity ); memset( - ucicmd_get_arg(*cmd, cmd->args_capacity - 32), + uci_cmd_get_arg(*cmd, cmd->args_capacity - 32), 0, 32 * MAX_TOKEN_SIZE ); @@ -81,11 +81,11 @@ void ucicmd_append_arg(ucicmd* cmd, const char* token) { if (i < MAX_TOKEN_SIZE) cmd->args[shift + i] = 0; } -char* ucicmd_get_arg(ucicmd cmd, int i) { +char* uci_cmd_get_arg(uci_cmd_t cmd, int i) { return cmd.args + i * MAX_TOKEN_SIZE; } -void ucicmd_deinit(ucicmd cmd) { +void uci_cmd_deinit(uci_cmd_t cmd) { free(cmd.args); } @@ -94,31 +94,31 @@ void ucicmd_deinit(ucicmd cmd) { #include <stdbool.h> #include <string.h> -bool test_ucicmd() { - ucicmd cmd = ucicmd_init(); - ucicmd_set_root(&cmd, "root"); - ucicmd_append_arg(&cmd, "arg1"); - ucicmd_append_arg(&cmd, "arg2"); - ucicmd_append_arg(&cmd, "arg3"); +bool test_uci_cmd_t() { + uci_cmd_t cmd = uci_cmd_init(); + uci_cmd_set_root(&cmd, "root"); + uci_cmd_append_arg(&cmd, "arg1"); + uci_cmd_append_arg(&cmd, "arg2"); + uci_cmd_append_arg(&cmd, "arg3"); if (strncmp(cmd.root, "root", MAX_TOKEN_SIZE) != 0) return false; - if (strncmp(ucicmd_get_arg(cmd, 0), "arg1", MAX_TOKEN_SIZE) != 0) + if (strncmp(uci_cmd_get_arg(cmd, 0), "arg1", MAX_TOKEN_SIZE) != 0) return false; - if (strncmp(ucicmd_get_arg(cmd, 1), "arg2", MAX_TOKEN_SIZE) != 0) + if (strncmp(uci_cmd_get_arg(cmd, 1), "arg2", MAX_TOKEN_SIZE) != 0) return false; - if (strncmp(ucicmd_get_arg(cmd, 2), "arg3", MAX_TOKEN_SIZE) != 0) + if (strncmp(uci_cmd_get_arg(cmd, 2), "arg3", MAX_TOKEN_SIZE) != 0) return false; return true; } -bool test_invalid_cmd_ucicmd() { - ucicmd cmd = ucicmd_init(); - ucicmd_add(&cmd, "john"); - ucicmd_add(&cmd, "debug"); - ucicmd_add(&cmd, "on"); +bool test_invalid_cmd_uci_cmd_t() { + uci_cmd_t cmd = uci_cmd_t_init(); + uci_cmd_add(&cmd, "john"); + uci_cmd_add(&cmd, "debug"); + uci_cmd_add(&cmd, "on"); if (strncmp(cmd.root, "debug", MAX_TOKEN_SIZE) != 0) return false; - if (strncmp(ucicmd_get_arg(cmd, 0), "on", MAX_TOKEN_SIZE) != 0) + if (strncmp(uci_cmd_t_get_arg(cmd, 0), "on", MAX_TOKEN_SIZE) != 0) return false; return true; } diff --git a/src/uci/response.c b/src/uci/response.c index 7ebe49c..da46cb7 100644 --- a/src/uci/response.c +++ b/src/uci/response.c @@ -2,113 +2,30 @@ #include <assert.h> #include <stdlib.h> -#include "response.h" -#include "ipc.h" +#include "uci/internals/response.h" +#include "uci/state.h" #include "fen.h" -#include "bitboard.h" -void apply_option(uci_state *state, char *name, char *buffer) { - int settings_count = sizeof(state->option_settings)/sizeof(option_setting_t); - for (int i = 0; i < settings_count; i++) { - option_setting_t setting = state->option_settings[i]; - - if (strcmp(setting.option_name, name)) continue; - if (OPTION_SPIN == setting.type) { - option_spin_setting_t data = setting.data.spin; - int num = atoi(buffer); - if (num < data.min) return; - if (num > data.max) return; - *setting.value.spin = num; - } else if (OPTION_COMBO == setting.type) { - option_combo_setting_t data = setting.data.combo; - for (int j = 0; j < data.count; j++) { - if (strcmp(data.combination[i], buffer)) continue; - *setting.value.combo = j; - } - } else if (OPTION_CHECK == setting.type) { - *setting.value.check = strcmp(buffer, "true") == 0; - } else if (OPTION_STRING == setting.type) { - free(setting.value.string->data); - setting.value.string->length = strlen(buffer); - setting.value.string->data = malloc(setting.value.string->length); - memcpy(setting.value.string->data, buffer, setting.value.string->length); - } else if (OPTION_BUTTON == setting.type) { - *setting.value.button = true; - } else { assert(0); } - return; - } - if (state->debug) { - printf("debug: invalid option\n"); - } -} - -// examples from uci_min.txt -// option name Nullmove type check default true\n -// option name Selectivity type spin default 2 min 0 max 4\n -// option name Style type combo default Normal var Solid var Normal var Risky\n -// option name NalimovPath type string default c:\\n -// option name Clear Hash type button\n -void print_setting(option_setting_t setting) { - printf("option name %s type ", setting.option_name); - // accidently did the yoda style if statement, i am keeping it - if (OPTION_SPIN == setting.type) { - option_spin_setting_t data = setting.data.spin; - printf( - "spin default %d min %d max %d\n", - data.default_value, - data.min, - data.max - ); - } else if (OPTION_COMBO == setting.type) { - option_combo_setting_t data = setting.data.combo; - printf("combo default %s", data.combination[data.default_index]); - for (int i = 0; i < data.count; i++) { - printf(" var %s", data.combination[i]); - } - printf("\n"); - } else if (OPTION_CHECK == setting.type) { - printf("check default %d\n", setting.data.check_default); - } else if (OPTION_STRING == setting.type) { - printf("string default %s\n", setting.data.string_default); - } else if (OPTION_BUTTON == setting.type) { - printf("button\n"); - } else { assert(0); } -} - -enum { - STATE_INITIAL, - STATE_IDLE, - STATE_SYNC, - STATE_PING, - STATE_ACTIVE, - STATE_HALT, -}; -int current_state = STATE_INITIAL; - -void handle_uci( - uci_state *state, - engine_messages *engine_message, - ucicmd cmd -) { - if (current_state == STATE_INITIAL) { +void handle_uci(uci_state_t *state, uci_cmd_t cmd) { + if (state->current_state == UCI_STATE_INITIAL) { return handle_initial(state, cmd); } - if (current_state == STATE_IDLE) { + if (state->current_state == UCI_STATE_IDLE) { return handle_idle(state, cmd); } - if (current_state == STATE_SYNC) { + if (state->current_state == UCI_STATE_SYNC) { return handle_sync(state, cmd); } - if (current_state == STATE_PING) { + if (state->current_state == UCI_STATE_PING) { return handle_ping(state, cmd); } - if (current_state == STATE_ACTIVE) { - return handle_active(state, engine_message, cmd); + if (state->current_state == UCI_STATE_ACTIVE) { + return handle_active(state, cmd); } return handle_halt(state, cmd); } -void handle_initial(uci_state *state, ucicmd cmd) { +void handle_initial(uci_state_t *state, uci_cmd_t cmd) { if (cmd.empty || strcmp(cmd.root, "uci") != 0) return; // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 5 SECONDS printf("id name %s\n", state->name); @@ -119,22 +36,20 @@ void handle_initial(uci_state *state, ucicmd cmd) { } // --- printf("uciok\n"); - current_state = STATE_IDLE; + state->current_state = UCI_STATE_IDLE; } -void handle_idle( - uci_state *state, - ucicmd cmd) { +void handle_idle(uci_state_t *state, uci_cmd_t cmd) { if (cmd.empty) return; if (strcmp(cmd.root, "debug") == 0) { - state->debug = strcmp(ucicmd_get_arg(cmd, 0), "on") == 0; + state->debug = strcmp(uci_cmd_get_arg(cmd, 0), "on") == 0; } else if (strcmp(cmd.root, "setoption") == 0) { char buffer[2048] = {0}; char name[64] = {0}; char *cursor = name; for (int i = 1; i < cmd.args_count; i++) { assert((long)cursor - (long)buffer < 2048); - char *arg = ucicmd_get_arg(cmd, i); + char *arg = uci_cmd_get_arg(cmd, i); if (strcmp(arg, "value") == 0) { *(--cursor) = 0; cursor = buffer; @@ -146,26 +61,18 @@ void handle_idle( *(--cursor) = 0; apply_option(state, name, buffer); } else if (strcmp(cmd.root, "ucinewgame") == 0) { - if (state->moves != NULL) { - free(state->moves); - state->moves = NULL; - state->moves_count = 0; - } } else if (strcmp(cmd.root, "position") == 0) { int k = 0; - char* mode = ucicmd_get_arg(cmd, 0); + char* mode = uci_cmd_get_arg(cmd, 0); if (strcmp(mode, "startpos") == 0) { struct fen_load fen = load_fen( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" ); - if (fen.failed) { - printf("info invalid fen\n"); - return; - } + assert(fen.failed == 0); state->position = fen.position; } else if (strcmp(mode, "fen") == 0) { - struct fen_load fen = load_fen(ucicmd_get_arg(cmd, k++)); + struct fen_load fen = load_fen(uci_cmd_get_arg(cmd, k++)); if (fen.failed) { printf("info invalid fen\n"); return; @@ -174,29 +81,21 @@ void handle_idle( } else { assert(0); } if (cmd.args_count >= k) return; - assert(strcmp(ucicmd_get_arg(cmd, k++), "moves") == 0); - assert(state->moves_count <= cmd.args_count - k); - int old_move_count = state->moves_count; - state->moves_count = cmd.args_count - k; - if (state->moves == NULL) { - state->moves = malloc( - state->moves_count * sizeof(struct uci_move) - ); - } else { - state->moves = realloc( - state->moves, - state->moves_count * sizeof(struct uci_move) - ); - } - int l = 0; + assert(strcmp(uci_cmd_get_arg(cmd, k++), "moves") == 0); + assert(state->moves->count <= cmd.args_count - k); + int old_move_count = state->moves->count; + state->moves->count = cmd.args_count - k; + k += old_move_count; - l += old_move_count; for (; k < cmd.args_count; k++) { - char* move = ucicmd_get_arg(cmd, k); - state->moves[l++] = (struct uci_move) { - (move[0] - 'a') * 8 + (move[1] - '1'), - (move[2] - 'a') * 8 + (move[3] - '1') - }; + char* move = uci_cmd_get_arg(cmd, k); + add_ipc_move( + state->moves, + (ipc_move_t) { + (move[0] - 'a') * 8 + (move[1] - '1'), + (move[2] - 'a') * 8 + (move[3] - '1') + } + ); } } else if (strcmp(cmd.root, "stop") == 0) { } else if (strcmp(cmd.root, "quit") == 0) { @@ -209,179 +108,101 @@ void handle_idle( free(setting.value.string->data); } - atomic_store(&state->quit, 1); + state->signal = UCI_SIGNAL_QUIT; } else if (strcmp(cmd.root, "isready") == 0) { - current_state = STATE_SYNC; + state->current_state = UCI_STATE_SYNC; } else if (strcmp(cmd.root, "go") == 0) { - state->go_args = malloc(sizeof(struct go_args)); - struct go_args *info = state->go_args; + go_args_t info = (go_args_t) {0}; for (int i = 0; i < cmd.args_count; i++) { - if (strcmp(ucicmd_get_arg(cmd, i), "searchmoves") == 0) { - info->searchmoves = comm_moves_init(); + if (strcmp(uci_cmd_get_arg(cmd, i), "searchmoves") == 0) { + ipc_moves_init(&info.searchmoves); for (i++; i < cmd.args_count; i++) { - char* move_str = ucicmd_get_arg(cmd, i); + char* move_str = uci_cmd_get_arg(cmd, i); if (move_str[1] < '0' || move_str[1] > '9') break; - add_comm_move(&info->searchmoves, (struct uci_move) { + add_ipc_move(&info.searchmoves, (ipc_move_t) { (move_str[0] - 'a') * 8 + (move_str[1] - '1'), (move_str[2] - 'a') * 8 + (move_str[3] - '1') }); } i--; - } else if (strcmp(ucicmd_get_arg(cmd, i), "ponder") == 0) { - info->ponder = true; - } else if (strcmp(ucicmd_get_arg(cmd, i), "wtime") == 0) { - info->wtime = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "btime") == 0) { - info->btime = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "winc") == 0) { - info->winc = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "binc") == 0) { - info->binc = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "movestogo") == 0) { - info->movestogo = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "depth") == 0) { - info->depth = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "nodes") == 0) { - info->nodes = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "mate") == 0) { - info->mate = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "movetime") == 0) { - info->movetime = atoi(ucicmd_get_arg(cmd, ++i)); - } else if (strcmp(ucicmd_get_arg(cmd, i), "infinite") == 0) { - info->infinite = true; - } else if (strcmp(ucicmd_get_arg(cmd, i), "perft") == 0) { - info->perft = atoi(ucicmd_get_arg(cmd, ++i)); + // it was harsh on my eyes, that's why i did this formatting + } else if (strcmp(uci_cmd_get_arg(cmd, i), "ponder") == 0) { + info.ponder = true; + } else if (strcmp(uci_cmd_get_arg(cmd, i), "wtime") == 0) { + info.wtime = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "btime") == 0) { + info.btime = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "winc") == 0) { + info.winc = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "binc") == 0) { + info.binc = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "movestogo") == 0) { + info.movestogo = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "depth") == 0) { + info.depth = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "nodes") == 0) { + info.nodes = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "mate") == 0) { + info.mate = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "movetime") == 0) { + info.movetime = atoi(uci_cmd_get_arg(cmd, ++i)); + } else if (strcmp(uci_cmd_get_arg(cmd, i), "infinite") == 0) { + info.infinite = true; + } else if (strcmp(uci_cmd_get_arg(cmd, i), "perft") == 0) { + info.perft = atoi(uci_cmd_get_arg(cmd, ++i)); } } - atomic_store(&state->go, 1); - current_state = STATE_ACTIVE; + memcpy(&state->go_args, &info, sizeof(info)); + state->signal = UCI_SIGNAL_GO; + state->current_state = UCI_STATE_ACTIVE; } else { printf("info violation\n"); } } -void handle_sync(uci_state *state, ucicmd cmd) { +void handle_sync(uci_state_t *state, uci_cmd_t cmd) { // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 5 SECONDS // --- printf("readyok\n"); - current_state = STATE_IDLE; + state->current_state = UCI_STATE_IDLE; } -void handle_ping(uci_state *state, ucicmd cmd) { +void handle_ping(uci_state_t *state, uci_cmd_t cmd) { // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 1 SECONDS // if (TODO) { // printf("bestmove\n"); - // current_state = STATE_IDLE; + // current_state = UCI_STATE_IDLE; // } // --- printf("readyok\n"); - current_state = STATE_ACTIVE; + state->current_state = UCI_STATE_ACTIVE; } -void handle_active( - uci_state *state, - engine_messages* engine_messages, - ucicmd cmd -) { - while (atomic_load(&state->go_ready_receive) == 0); - - bool ended = false; - for (int i = 0; i < engine_messages->count; i++) { - struct engine_message *old = engine_messages->data[i]; - if (old == NULL) continue; - if (!old->ready) continue; - old->ready = 0; - - printf( - "info depth %d seldepth %d multipv %d ", - old->depth, - old->seldepth, - old->multipv - ); - if (old->mate) { - printf("mate %d ", old->mate); - } else { - printf("score cp %d ", old->score_cp); - } - if (old->node_limit) { - printf("upperbound "); - } - printf( - "nodes %d nps %d hashfull %d tbhits %d time %d pv", - old->nodes, - old->nps, - old->hashfull, - old->tbhits, - old->time - ); - - for (int j = 0; j < old->pv.count; j++) { - struct uci_move move = old->pv.moves[i]; - printf( - " %c%c%c%c", - (move.from / 8) + 'a', - (move.from % 8) + '1', - (move.to / 8) + 'a', - (move.to % 8) + '1' - ); - } - printf("\n"); - - if (old->best_move.from != 0 && old->best_move.to != 0) { - ended = true; - printf( - "bestmove %c%c%c%c", - (old->best_move.from / 8) + 'a', - (old->best_move.from % 8) + '1', - (old->best_move.to / 8) + 'a', - (old->best_move.to % 8) + '1' - ); - if (old->ponder.from != 0 && old->ponder.to != 0) { - printf( - " ponder %c%c%c%c", - (old->ponder.from / 8) + 'a', - (old->ponder.from % 8) + '1', - (old->ponder.to / 8) + 'a', - (old->ponder.to % 8) + '1' - ); - } - printf("\n"); - } - - engine_messages->data[i] = old->next; - free(old->pv.moves); - free(old); - - if (ended) { - printf("ENDED\n"); - atomic_store(&state->cleanup, 1); - current_state = STATE_IDLE; - } - } +void handle_active(uci_state_t *state, uci_cmd_t cmd) { if (cmd.empty) { return; } if (strcmp(cmd.root, "isready") == 0) { - current_state = STATE_PING; + state->current_state = UCI_STATE_PING; } else if (strcmp(cmd.root, "stop") == 0) { - current_state = STATE_HALT; + state->current_state = UCI_STATE_HALT; } else { printf("info violation\n"); } } -void handle_halt(uci_state *state, ucicmd cmd) { +void handle_halt(uci_state_t *state, uci_cmd_t cmd) { // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 1 SECONDS - - atomic_store(&state->stop, 1); + + state->signal = UCI_SIGNAL_STOP; // --- - current_state = STATE_IDLE; + state->current_state = UCI_STATE_IDLE; } diff --git a/src/uci/state.c b/src/uci/state.c index 56e0b04..ac043ed 100644 --- a/src/uci/state.c +++ b/src/uci/state.c @@ -1,80 +1,219 @@ #include <string.h> -#include "state.h" +#include "uci/state.h" -option_setting_t option_setting_combo( - char* option_name, - char** combinations, +void option_setting_combo( + option_setting_t *target, + char *option_name, + char **combinations, int combinations_count, int default_index, combo_t *combo ) { - option_setting_t output = {0}; - strncpy(output.option_name, option_name, 32); - output.type = OPTION_COMBO; - output.data.combo = (option_combo_setting_t) { + strncpy(target->option_name, option_name, 32); + target->type = OPTION_COMBO; + target->data.combo = (option_combo_setting_t) { combinations, combinations_count, default_index }; - output.value.combo = combo; + target->value.combo = combo; *combo = default_index; - return output; } -option_setting_t option_setting_spin( - const char* option_name, +void option_setting_spin( + option_setting_t *target, + const char *option_name, int min, int max, int default_value, spin_t *spin ) { - option_setting_t output = {0}; - strncpy(output.option_name, option_name, 32); - output.type = OPTION_SPIN; - output.data.spin = (option_spin_setting_t) { min, max, default_value }; - output.value.spin = spin; + strncpy(target->option_name, option_name, 32); + target->type = OPTION_SPIN; + target->data.spin = (option_spin_setting_t) { min, max, default_value }; + target->value.spin = spin; *spin = default_value; - return output; } -option_setting_t option_setting_check( - const char* option_name, +void option_setting_check( + option_setting_t *target, + const char *option_name, bool default_value, check_t *check ) { - option_setting_t output = {0}; - strncpy(output.option_name, option_name, 32); - output.type = OPTION_CHECK; - output.data.check_default = default_value; - output.value.check = check; + strncpy(target->option_name, option_name, 32); + target->type = OPTION_CHECK; + target->data.check_default = default_value; + target->value.check = check; *check = default_value; - return output; } -option_setting_t option_setting_string( - const char* option_name, - const char* default_value, +void option_setting_string( + option_setting_t *target, + const char *option_name, + const char *default_value, str_t *string ) { - option_setting_t output = {0}; - strncpy(output.option_name, option_name, 32); - output.type = OPTION_STRING; - output.data.string_default = default_value; - output.value.string = string; + strncpy(target->option_name, option_name, 32); + target->type = OPTION_STRING; + target->data.string_default = default_value; + target->value.string = string; string->length = strlen(default_value); string->data = malloc(string->length); memcpy(string->data, default_value, string->length); - return output; } -option_setting_t option_setting_button( - const char* option_name, +void option_setting_button( + option_setting_t *target, + const char *option_name, button_t *button ) { - option_setting_t output = {0}; - strncpy(output.option_name, option_name, 32); - output.type = OPTION_BUTTON; - output.value.button = button; + strncpy(target->option_name, option_name, 32); + target->type = OPTION_BUTTON; + target->value.button = button; *button = false; - return output; } + +// examples from uci_min.txt +// option name Nullmove type check default true\n +// option name Selectivity type spin default 2 min 0 max 4\n +// option name Style type combo default Normal var Solid var Normal var Risky\n +// option name NalimovPath type string default c:\\n +// option name Clear Hash type button\n +void print_setting(option_setting_t setting) { + printf("option name %s type ", setting.option_name); + // accidently did the yoda style if statement, i am keeping it + if (OPTION_SPIN == setting.type) { + option_spin_setting_t data = setting.data.spin; + printf( + "spin default %d min %d max %d\n", + data.default_value, + data.min, + data.max + ); + } else if (OPTION_COMBO == setting.type) { + option_combo_setting_t data = setting.data.combo; + printf("combo default %s", data.combination[data.default_index]); + for (int i = 0; i < data.count; i++) { + printf(" var %s", data.combination[i]); + } + printf("\n"); + } else if (OPTION_CHECK == setting.type) { + printf("check default %d\n", setting.data.check_default); + } else if (OPTION_STRING == setting.type) { + printf("string default %s\n", setting.data.string_default); + } else if (OPTION_BUTTON == setting.type) { + printf("button\n"); + } else { assert(0); } +} + +void uci_state_init(uci_state_t *state) { + state->signal = UCI_SIGNAL_NONE; + strncpy(state->name, "Gacrux", 32); + strncpy(state->author, "Aargh Rai <aarghrai.com>", 32); + int k = 0; + option_setting_spin( + state->option_settings + k++, + "Threads", + 1, 5, 1, + &state->threads + ); + option_setting_spin( + state->option_settings + k++, + "Hash", + 0, 512, 256, + &state->hash + ); + option_setting_button( + state->option_settings + k++, + "Clear Hash", + &state->clear_hash + ); + option_setting_check( + state->option_settings + k++, + "UCI_ShowCurrLine", + false, + &state->uci_showcurrline + ); + option_setting_check( + state->option_settings + k++, + "UCI_ShowRefutations", + false, + &state->uci_showrefutations + ); + option_setting_check( + state->option_settings + k++, + "UCI_LimitStrength", + false, + &state->uci_limitstrength + ); + option_setting_spin( + state->option_settings + k++, + "UCI_Elo", + 100, 3500, 800, + &state->uci_elo + ); + option_setting_check( + state->option_settings + k++, + "UCI_AnalyseMode", + false, + &state->uci_analysemode + ); + option_setting_string( + state->option_settings + k++, + "UCI_Opponent", + "<empty>", + &state->uci_opponent + ); + option_setting_string( + state->option_settings + k++, + "UCI_EngineAbout", + "Gacrux by Aargh Rai, Checkout https://git.aarghrai.com/gacrux", + &state->uci_engineabout + ); + option_setting_string( + state->option_settings + k++, + "UCI_SetPositionValue", + "<empty>", + &state->uci_setpositionvalue + ); +} + +void uci_state_deinit(uci_state_t *state) {} + +void apply_option(uci_state_t *state, char *name, char *buffer) { + int settings_count = sizeof(state->option_settings)/sizeof(option_setting_t); + for (int i = 0; i < settings_count; i++) { + option_setting_t setting = state->option_settings[i]; + if (strcmp(setting.option_name, name)) continue; + if (OPTION_SPIN == setting.type) { + option_spin_setting_t data = setting.data.spin; + int num = atoi(buffer); + if (num < data.min) return; + if (num > data.max) return; + *setting.value.spin = num; + } else if (OPTION_COMBO == setting.type) { + option_combo_setting_t data = setting.data.combo; + for (int j = 0; j < data.count; j++) { + if (strcmp(data.combination[i], buffer)) continue; + *setting.value.combo = j; + } + } else if (OPTION_CHECK == setting.type) { + *setting.value.check = strcmp(buffer, "true") == 0; + } else if (OPTION_STRING == setting.type) { + free(setting.value.string->data); + setting.value.string->length = strlen(buffer); + setting.value.string->data = malloc(setting.value.string->length); + memcpy(setting.value.string->data, buffer, setting.value.string->length); + } else if (OPTION_BUTTON == setting.type) { + *setting.value.button = true; + } else { assert(0); } + + memcpy(state->option_settings + i, &setting, sizeof(setting)); + return; + } + if (state->debug) { + printf("info invalid option\n"); + } +} + diff --git a/symbol_analyzer/analysis.js b/symbol_analyzer/analysis.js new file mode 100644 index 0000000..3181318 --- /dev/null +++ b/symbol_analyzer/analysis.js @@ -0,0 +1 @@ +data = [{"name": "stdbool.h", "imports": [], "symbols": ["bool"], "unused": ["bool"], "used": []}, {"name": "uci.h", "imports": ["stdint.h", "mman.h", "stdatomic.h", "state.h", "bitboard.h", "ipc.h", "stdbool.h", "stdlib.h", "inttypes.h", "fen.h", "ints.h"], "symbols": ["uci", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "WHITE_QUEEN", "engine_message", "engine_messages", "option_setting_button", "OPTION_STRING", "int", "should_continue", "go_args", "uci_state", "WHITE_BISHOP", "option_setting_spin", "option_setting_t", "option_combo_setting_t", "comm_moves", "comms", "BLACK_ROOK", "option_setting_string", "OPTION_SPIN", "WHITE_ROOK", "OPTION_CHECK", "MESSAGE_READ", "option_spin_setting_t", "PIECE_TYPE_COUNT", "assert_valid_position", "combo_t", "position_starting", "occupied_by", "WHITE_KING", "comm_moves_init", "str_t", "option_setting_check", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "uci_move", "OPTION_BUTTON", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "add_comm_move", "MESSAGE_FILLED", "MESSAGE_PROCESSED", "spin_t", "bool", "fen_load", "WHITE_PAWN", "option_setting_combo", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN"], "used": ["uci"]}, {"name": "ints.h", "imports": ["stdint.h", "inttypes.h"], "symbols": ["int", "char"], "unused": ["int", "char"], "used": []}, {"name": "bitboard.h", "imports": ["stdint.h", "stdbool.h", "inttypes.h", "ints.h"], "symbols": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "WHITE_QUEEN", "int", "WHITE_BISHOP", "BLACK_ROOK", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "WHITE_KING", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "position_t", "char", "WHITE_KNIGHT", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN"], "unused": ["WHITE_SHORT_CASTLE", "BLACK_TURN", "BLACK_LONG_CASTLE", "PIECE_TYPE_COUNT", "WHITE_LONG_CASTLE", "char", "BLACK_SHORT_CASTLE", "WHITE_TURN", "int"], "used": ["blacks", "WHITE_QUEEN", "WHITE_BISHOP", "BLACK_ROOK", "WHITE_ROOK", "assert_valid_position", "position_starting", "occupied_by", "WHITE_KING", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_BISHOP", "position_t", "WHITE_KNIGHT", "bool", "WHITE_PAWN", "BLACK_KING", "BLACK_PAWN", "BLACK_QUEEN"]}, {"name": "ipc.h", "imports": ["stdint.h", "mman.h", "stdatomic.h", "state.h", "bitboard.h", "stdbool.h", "stdlib.h", "inttypes.h", "fen.h", "ints.h"], "symbols": ["MESSAGE_READ", "go_args", "add_comm_move", "should_continue", "char", "MESSAGE_FILLED", "MESSAGE_PROCESSED", "engine_message", "engine_messages", "comm_moves_init", "comm_moves", "comms", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "engine_message", "WHITE_QUEEN", "engine_messages", "option_setting_button", "int", "go_args", "uci_state", "WHITE_BISHOP", "option_setting_spin", "option_setting_t", "option_combo_setting_t", "comms", "BLACK_ROOK", "option_setting_string", "OPTION_SPIN", "MESSAGE_READ", "OPTION_CHECK", "WHITE_ROOK", "option_spin_setting_t", "PIECE_TYPE_COUNT", "assert_valid_position", "combo_t", "position_starting", "occupied_by", "WHITE_KING", "str_t", "option_setting_check", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "uci_move", "OPTION_BUTTON", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "char", "MESSAGE_FILLED", "MESSAGE_PROCESSED", "BLACK_TURN", "position_t", "WHITE_KNIGHT", "spin_t", "fen_load", "WHITE_PAWN", "option_setting_combo", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "OPTION_STRING", "BLACK_QUEEN"], "used": ["should_continue", "add_comm_move", "bool", "comm_moves_init", "comm_moves"]}, {"name": "fen.h", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "inttypes.h", "ints.h"], "symbols": ["fen_load", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "WHITE_LONG_CASTLE", "blacks", "WHITE_QUEEN", "position_starting", "occupied_by", "WHITE_KING", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "int", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "WHITE_BISHOP", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "fen_load", "bool", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_ROOK", "BLACK_QUEEN"], "used": []}, {"name": "state.h", "imports": ["stdint.h", "stdatomic.h", "bitboard.h", "stdbool.h", "inttypes.h", "fen.h", "ints.h"], "symbols": ["OPTION_COMBO", "option_setting_button", "int", "uci_state", "option_setting_spin", "option_setting_t", "option_combo_setting_t", "option_setting_string", "OPTION_SPIN", "OPTION_CHECK", "option_spin_setting_t", "combo_t", "str_t", "option_setting_check", "uci_move", "OPTION_BUTTON", "char", "spin_t", "option_setting_combo", "OPTION_STRING"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "WHITE_QUEEN", "int", "uci_state", "WHITE_BISHOP", "option_combo_setting_t", "BLACK_ROOK", "OPTION_SPIN", "WHITE_ROOK", "OPTION_CHECK", "option_spin_setting_t", "PIECE_TYPE_COUNT", "assert_valid_position", "combo_t", "position_starting", "occupied_by", "WHITE_KING", "str_t", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "uci_move", "OPTION_BUTTON", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "fen_load", "spin_t", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "OPTION_STRING", "BLACK_QUEEN"], "used": ["option_setting_spin", "bool", "option_setting_t", "option_setting_combo", "option_setting_check", "option_setting_button", "option_setting_string"]}, {"name": "response.h", "imports": ["stdint.h", "mman.h", "stdatomic.h", "state.h", "bitboard.h", "ipc.h", "stdbool.h", "stdlib.h", "inttypes.h", "fen.h", "command.h", "ints.h"], "symbols": ["handle_idle", "handle_halt", "char", "handle_initial", "handle_ping", "handle_sync", "handle_active", "handle_uci", "int"], "unused": ["WHITE_LONG_CASTLE", "WHITE_QUEEN", "option_setting_button", "should_continue", "ucicmd_set_root", "uci_state", "option_combo_setting_t", "comm_moves", "ucicmd", "comms", "OPTION_SPIN", "MESSAGE_READ", "option_spin_setting_t", "combo_t", "occupied_by", "WHITE_KING", "option_setting_check", "print_bitboard", "check_valid_position", "whites", "BLACK_TURN", "add_comm_move", "WHITE_KNIGHT", "MESSAGE_FILLED", "bool", "fen_load", "option_setting_combo", "BLACK_KING", "BLACK_PAWN", "BLACK_QUEEN", "WHITE_SHORT_CASTLE", "blacks", "OPTION_COMBO", "engine_message", "ucicmd_append_arg", "engine_messages", "ucicmd_add", "int", "go_args", "WHITE_BISHOP", "option_setting_spin", "option_setting_t", "BLACK_ROOK", "option_setting_string", "OPTION_CHECK", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "ucicmd_get_arg", "position_starting", "comm_moves_init", "str_t", "WHITE_TURN", "ucicmd_deinit", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "uci_move", "OPTION_BUTTON", "BLACK_BISHOP", "char", "position_t", "MESSAGE_PROCESSED", "spin_t", "WHITE_PAWN", "BLACK_SHORT_CASTLE", "OPTION_STRING", "ucicmd_init"], "used": ["handle_idle", "handle_halt", "handle_initial", "handle_ping", "handle_sync", "handle_uci", "handle_active"]}, {"name": "command.h", "imports": [], "symbols": ["ucicmd_deinit", "ucicmd_set_root", "ucicmd_get_arg", "char", "ucicmd_append_arg", "ucicmd", "ucicmd_add", "ucicmd_init", "int"], "unused": ["int"], "used": ["ucicmd_deinit", "ucicmd_set_root", "ucicmd_get_arg", "char", "ucicmd_append_arg", "ucicmd", "ucicmd_add", "ucicmd_init"]}, {"name": "moves.h", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "inttypes.h", "ints.h"], "symbols": ["MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "get_queen_moves", "get_rook_moves", "MOVE_PROMOTE_B", "moves_t", "int", "__forloop_rook_moves_gen", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "MOVE_LONG_CASTLE", "position_make_move", "MOVE_CAPTURE", "add_move_params", "MOVE_CHECK", "MOVE_PROMOTE_N", "get_knight_moves", "move_t", "get_pawn_moves", "char", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "get_moves", "moves_empty", "_add_move", "moves_init_wcapacity", "add_move"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "MOVE_PROMOTE_B", "int", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "BLACK_ROOK", "MOVE_LONG_CASTLE", "MOVE_CAPTURE", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "MOVE_PROMOTE_N", "check_valid_position", "whites", "BLACK_KNIGHT", "move_t", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "bool", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN"], "used": ["add_move", "get_pawn_moves", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "get_queen_moves", "get_moves", "get_rook_moves", "get_king_moves", "position_make_move", "moves_empty", "_add_move", "moves_init_wcapacity", "moves_t", "get_knight_moves", "__forloop_rook_moves_gen"]}, {"name": "fen.c", "imports": ["stdint.h", "assert.h", "bitboard.h", "stdbool.h", "inttypes.h", "fen.h", "ints.h"], "symbols": ["get_castling", "get_piece_enum_item", "letters", "char", "fen_load", "get_turn", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "WHITE_QUEEN", "WHITE_BISHOP", "BLACK_ROOK", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "WHITE_KING", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "fen_load", "bool", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN"], "used": ["get_castling", "get_piece_enum_item", "letters", "get_turn", "int"]}, {"name": "bitboard.c", "imports": ["stdint.h", "assert.h", "stdio.h", "bitboard.h", "stdbool.h", "inttypes.h", "ints.h"], "symbols": ["assert_valid_position", "char", "position_starting", "print_bitboard", "check_valid_position", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "WHITE_QUEEN", "int", "WHITE_BISHOP", "BLACK_ROOK", "WHITE_ROOK", "PIECE_TYPE_COUNT", "occupied_by", "WHITE_KING", "WHITE_TURN", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "char", "WHITE_KNIGHT", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN"], "used": ["assert_valid_position", "bool", "position_t", "position_starting", "print_bitboard", "check_valid_position"]}, {"name": "ipc.c", "imports": ["stdint.h", "mman.h", "assert.h", "stdatomic.h", "state.h", "bitboard.c", "stdio.h", "bitboard.h", "ipc.h", "stdbool.h", "stdlib.h", "inttypes.h", "fen.h", "fen.c", "ints.h"], "symbols": ["should_continue", "add_comm_move", "return", "char", "if", "comm_moves_init", "realloc", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "WHITE_QUEEN", "engine_message", "engine_messages", "option_setting_button", "go_args", "uci_state", "WHITE_BISHOP", "option_setting_spin", "option_setting_t", "option_combo_setting_t", "comms", "BLACK_ROOK", "option_setting_string", "OPTION_SPIN", "WHITE_ROOK", "OPTION_CHECK", "MESSAGE_READ", "option_spin_setting_t", "assert_valid_position", "PIECE_TYPE_COUNT", "get_piece_enum_item", "letters", "combo_t", "position_starting", "occupied_by", "WHITE_KING", "str_t", "option_setting_check", "print_bitboard", "WHITE_TURN", "check_valid_position", "get_turn", "whites", "get_castling", "BLACK_KNIGHT", "uci_move", "OPTION_BUTTON", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "char", "BLACK_TURN", "position_t", "WHITE_KNIGHT", "MESSAGE_FILLED", "MESSAGE_PROCESSED", "spin_t", "fen_load", "WHITE_PAWN", "option_setting_combo", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "OPTION_STRING", "BLACK_QUEEN"], "used": ["should_continue", "add_comm_move", "return", "bool", "if", "comm_moves_init", "comm_moves", "realloc", "int"]}, {"name": "uci.c", "imports": ["unistd.h", "assert.h", "stdio.h", "ipc.h", "command.c", "stdbool.h", "fcntl.h", "inttypes.h", "mman.h", "response.h", "stdatomic.h", "uci.h", "stdlib.h", "string.h", "command.h", "stdint.h", "state.c", "state.h", "bitboard.h", "response.c", "fen.h", "ints.h"], "symbols": ["uci", "load_from_message", "int", "char"], "unused": ["WHITE_LONG_CASTLE", "atoi", "WHITE_QUEEN", "STATE_IDLE", "option_setting_button", "should_continue", "ucicmd_set_root", "uci_state", "print_setting", "is_valid_cmd", "STATE_INITIAL", "option_combo_setting_t", "STATE_SYNC", "handle_sync", "comm_moves", "printf", "ucicmd", "comms", "free", "handle_active", "OPTION_SPIN", "MESSAGE_READ", "option_spin_setting_t", "handle_halt", "sizeof", "combo_t", "occupied_by", "test_ucicmd", "WHITE_KING", "option_setting_check", "print_bitboard", "check_valid_position", "while", "whites", "BLACK_TURN", "add_comm_move", "bool", "MESSAGE_FILLED", "WHITE_KNIGHT", "fen_load", "option_setting_combo", "BLACK_KING", "BLACK_PAWN", "BLACK_QUEEN", "WHITE_SHORT_CASTLE", "blacks", "OPTION_COMBO", "engine_message", "ucicmd_append_arg", "engine_messages", "handle_ping", "realloc", "assert", "ucicmd_add", "int", "go_args", "WHITE_BISHOP", "strcmp", "option_setting_spin", "apply_option", "stpncpy", "option_setting_t", "BLACK_ROOK", "atomic_store", "option_setting_string", "STATE_PING", "handle_idle", "WHITE_ROOK", "OPTION_CHECK", "malloc", "PIECE_TYPE_COUNT", "assert_valid_position", "ucicmd_get_arg", "if", "handle_initial", "position_starting", "comm_moves_init", "str_t", "WHITE_TURN", "ucicmd_deinit", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "OPTION_BUTTON", "uci_move", "STATE_ACTIVE", "char", "MESSAGE_PROCESSED", "STATE_HALT", "for", "position_t", "spin_t", "test_invalid_cmd_ucicmd", "WHITE_PAWN", "BLACK_SHORT_CASTLE", "OPTION_STRING", "ucicmd_init", "handle_uci"], "used": ["uci", "load_from_message"]}, {"name": "engine.c", "imports": ["unistd.h", "assert.h", "stdio.h", "knight.c", "ipc.h", "stdbool.h", "fcntl.h", "pthread.h", "inttypes.h", "moves.c", "mman.h", "stdatomic.h", "uci.h", "stdlib.h", "moves.h", "string.h", "stdint.h", "state.h", "bitboard.h", "fen.h", "vec.c", "ints.h", "rook.c", "pawn.c", "bishop.c", "king.c", "queen.c"], "symbols": ["thread_args", "decrease_threads", "engine_message", "realloc", "main", "int", "send_stop_signal", "printf", "pthread_cancel", "free", "atomic_store", "malloc", "engine_thread", "if", "threads", "comm_moves_init", "all_stopped", "while", "add_comm_move", "pthread_create", "set_threads", "for", "char", "increase_threads"], "unused": ["MOVE_PROMOTE_R", "get_queen_moves", "moves_t", "option_setting_button", "min", "comm_moves", "test_black_king_corners", "combo_t", "occupied_by", "WHITE_KING", "MOVE_CHECK", "option_setting_check", "MOVE_PROMOTE_N", "BLACK_TURN", "move_t", "MESSAGE_FILLED", "__forloop_bishop_moves_gen", "option_setting_combo", "BLACK_PAWN", "moves_init_wcapacity", "WHITE_SHORT_CASTLE", "OPTION_COMBO", "assert", "go_args", "option_setting_t", "get_king_moves", "find_piece_on_square", "BLACK_ROOK", "add_promote_moves", "MOVE_CAPTURE", "WHITE_ROOK", "position_starting", "threads", "get_knight_moves", "BLACK_KNIGHT", "test_white_king_corners", "BLACK_BISHOP", "OPTION_BUTTON", "char", "MESSAGE_PROCESSED", "get_bishop_moves", "spin_t", "moves_empty", "add_move_params", "add_move", "WHITE_LONG_CASTLE", "WHITE_QUEEN", "get_rook_moves", "should_continue", "uci_state", "MOVE_PROMOTE_Q", "option_combo_setting_t", "position_make_move", "MESSAGE_READ", "OPTION_SPIN", "option_spin_setting_t", "print_bitboard", "check_valid_position", "whites", "WHITE_KNIGHT", "fen_load", "get_moves", "_add_move", "BLACK_KING", "uci", "BLACK_QUEEN", "thread_args", "blacks", "MOVE_SHORT_CASTLE", "engine_message", "engine_messages", "MOVE_PROMOTE_B", "__forloop_rook_moves_gen", "WHITE_BISHOP", "get_black_pawn_forwardmoves", "option_setting_spin", "MOVE_EN_PASSANT", "get_white_pawn_forwardmoves", "MOVE_LONG_CASTLE", "option_setting_string", "OPTION_CHECK", "PIECE_TYPE_COUNT", "assert_valid_position", "str_t", "WHITE_TURN", "BLACK_LONG_CASTLE", "uci_move", "get_pawn_moves", "moves_init", "position_t", "WHITE_PAWN", "BLACK_SHORT_CASTLE", "OPTION_STRING"], "used": ["decrease_threads", "realloc", "main", "int", "send_stop_signal", "printf", "pthread_cancel", "comms", "free", "atomic_store", "malloc", "engine_thread", "if", "comm_moves_init", "all_stopped", "while", "add_comm_move", "pthread_create", "set_threads", "for", "bool", "increase_threads"]}, {"name": "command.c", "imports": ["assert.h", "stdbool.h", "stdlib.h", "string.h", "command.h"], "symbols": ["ucicmd_deinit", "ucicmd_set_root", "ucicmd_get_arg", "char", "is_valid_cmd", "test_ucicmd", "ucicmd_append_arg", "test_invalid_cmd_ucicmd", "ucicmd_add", "ucicmd_init", "int"], "unused": ["int"], "used": ["ucicmd_deinit", "ucicmd_set_root", "ucicmd_get_arg", "char", "is_valid_cmd", "bool", "test_ucicmd", "ucicmd_append_arg", "test_invalid_cmd_ucicmd", "ucicmd", "ucicmd_add", "ucicmd_init"]}, {"name": "response.c", "imports": ["stdint.h", "mman.h", "assert.h", "response.h", "stdatomic.h", "state.h", "bitboard.h", "ipc.h", "stdbool.h", "stdlib.h", "inttypes.h", "fen.h", "string.h", "command.h", "ints.h"], "symbols": ["atoi", "engine_message", "STATE_IDLE", "handle_ping", "realloc", "assert", "int", "go_args", "strcmp", "print_setting", "apply_option", "STATE_INITIAL", "stpncpy", "STATE_SYNC", "handle_sync", "printf", "free", "atomic_store", "handle_active", "STATE_PING", "handle_idle", "malloc", "handle_halt", "sizeof", "ucicmd_get_arg", "if", "handle_initial", "comm_moves_init", "while", "STATE_ACTIVE", "uci_move", "add_comm_move", "STATE_HALT", "for", "char", "fen_load", "handle_uci"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "WHITE_QUEEN", "engine_message", "ucicmd_append_arg", "engine_messages", "ucicmd_add", "option_setting_button", "should_continue", "go_args", "ucicmd_set_root", "uci_state", "WHITE_BISHOP", "option_setting_spin", "option_combo_setting_t", "comm_moves", "ucicmd", "comms", "BLACK_ROOK", "option_setting_string", "OPTION_SPIN", "WHITE_ROOK", "MESSAGE_READ", "OPTION_CHECK", "option_spin_setting_t", "PIECE_TYPE_COUNT", "assert_valid_position", "combo_t", "occupied_by", "position_starting", "WHITE_KING", "str_t", "option_setting_check", "print_bitboard", "WHITE_TURN", "check_valid_position", "whites", "ucicmd_deinit", "BLACK_TURN", "BLACK_KNIGHT", "BLACK_BISHOP", "OPTION_BUTTON", "uci_move", "BLACK_LONG_CASTLE", "MESSAGE_PROCESSED", "MESSAGE_FILLED", "WHITE_KNIGHT", "fen_load", "position_t", "ucicmd_init", "spin_t", "WHITE_PAWN", "option_setting_combo", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "OPTION_STRING", "BLACK_QUEEN"], "used": ["atoi", "STATE_IDLE", "handle_ping", "realloc", "assert", "int", "strcmp", "print_setting", "apply_option", "STATE_INITIAL", "stpncpy", "option_setting_t", "STATE_SYNC", "handle_sync", "printf", "free", "atomic_store", "handle_active", "STATE_PING", "handle_idle", "malloc", "handle_halt", "ucicmd_get_arg", "sizeof", "if", "handle_initial", "comm_moves_init", "while", "add_comm_move", "STATE_ACTIVE", "STATE_HALT", "for", "bool", "char", "handle_uci"]}, {"name": "state.c", "imports": ["stdint.h", "stdatomic.h", "state.h", "bitboard.h", "stdbool.h", "inttypes.h", "fen.h", "string.h", "ints.h"], "symbols": ["option_setting_spin", "char", "option_setting_combo", "option_setting_check", "option_setting_button", "option_setting_string", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "OPTION_COMBO", "WHITE_QUEEN", "int", "uci_state", "WHITE_BISHOP", "option_combo_setting_t", "BLACK_ROOK", "OPTION_SPIN", "WHITE_ROOK", "OPTION_CHECK", "option_spin_setting_t", "PIECE_TYPE_COUNT", "assert_valid_position", "combo_t", "position_starting", "occupied_by", "WHITE_KING", "str_t", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "uci_move", "OPTION_BUTTON", "BLACK_BISHOP", "BLACK_TURN", "char", "position_t", "WHITE_KNIGHT", "bool", "fen_load", "spin_t", "WHITE_PAWN", "BLACK_KING", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "OPTION_STRING", "BLACK_QUEEN"], "used": ["option_setting_spin", "option_setting_t", "option_setting_combo", "option_setting_check", "option_setting_button", "option_setting_string"]}, {"name": "moves.c", "imports": ["stdint.h", "rook.c", "assert.h", "moves.h", "stdio.h", "bitboard.h", "pawn.c", "knight.c", "stdbool.h", "stdlib.h", "bishop.c", "king.c", "inttypes.h", "queen.c", "vec.c", "ints.h"], "symbols": ["char", "get_moves", "find_piece_on_square", "int", "position_make_move"], "unused": ["WHITE_LONG_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "get_queen_moves", "get_rook_moves", "moves_t", "min", "MOVE_PROMOTE_Q", "test_black_king_corners", "occupied_by", "WHITE_KING", "MOVE_CHECK", "print_bitboard", "MOVE_PROMOTE_N", "check_valid_position", "whites", "BLACK_TURN", "move_t", "WHITE_KNIGHT", "bool", "__forloop_bishop_moves_gen", "_add_move", "BLACK_KING", "moves_init_wcapacity", "BLACK_PAWN", "BLACK_QUEEN", "WHITE_SHORT_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "realloc", "MOVE_PROMOTE_B", "assert", "__forloop_rook_moves_gen", "WHITE_BISHOP", "get_black_pawn_forwardmoves", "MOVE_EN_PASSANT", "get_white_pawn_forwardmoves", "get_king_moves", "MOVE_LONG_CASTLE", "BLACK_ROOK", "add_promote_moves", "MOVE_CAPTURE", "WHITE_ROOK", "PIECE_TYPE_COUNT", "assert_valid_position", "if", "position_starting", "WHITE_TURN", "get_knight_moves", "BLACK_KNIGHT", "test_white_king_corners", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "get_pawn_moves", "char", "moves_init", "position_t", "get_bishop_moves", "WHITE_PAWN", "moves_empty", "BLACK_SHORT_CASTLE", "add_move_params", "add_move"], "used": ["find_piece_on_square", "get_moves", "int", "position_make_move"]}, {"name": "king.c", "imports": ["stdint.h", "assert.h", "stdio.h", "bitboard.h", "stdbool.h", "stdlib.h", "moves.h", "inttypes.h", "vec.c", "ints.h"], "symbols": ["test_white_king_corners", "char", "test_black_king_corners", "get_king_moves", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_queen_moves", "get_rook_moves", "realloc", "MOVE_PROMOTE_B", "assert", "moves_t", "int", "__forloop_rook_moves_gen", "min", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "if", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "char", "position_t", "WHITE_KNIGHT", "get_pawn_moves", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["test_white_king_corners", "get_king_moves", "test_black_king_corners", "bool"]}, {"name": "knight.c", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["get_knight_moves", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_queen_moves", "get_rook_moves", "MOVE_PROMOTE_B", "moves_t", "int", "__forloop_rook_moves_gen", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "whites", "MOVE_PROMOTE_N", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "get_pawn_moves", "char", "position_t", "WHITE_KNIGHT", "bool", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["get_knight_moves"]}, {"name": "bishop.c", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["__forloop_bishop_moves_gen", "get_bishop_moves", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_queen_moves", "get_rook_moves", "MOVE_PROMOTE_B", "moves_t", "int", "__forloop_rook_moves_gen", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "get_pawn_moves", "char", "position_t", "WHITE_KNIGHT", "bool", "moves_init", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["__forloop_bishop_moves_gen", "get_bishop_moves"]}, {"name": "pawn.c", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["get_pawn_moves", "get_black_pawn_forwardmoves", "char", "get_white_pawn_forwardmoves", "add_promote_moves", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_queen_moves", "get_rook_moves", "MOVE_PROMOTE_B", "moves_t", "int", "__forloop_rook_moves_gen", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "char", "position_t", "WHITE_KNIGHT", "bool", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["get_white_pawn_forwardmoves", "get_pawn_moves", "get_black_pawn_forwardmoves", "add_promote_moves"]}, {"name": "vec.c", "imports": ["stdint.h", "assert.h", "bitboard.h", "stdbool.h", "stdlib.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["min", "moves_init", "char", "if", "moves_empty", "_add_move", "realloc", "assert", "moves_init_wcapacity", "int"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "get_queen_moves", "get_rook_moves", "MOVE_PROMOTE_B", "__forloop_rook_moves_gen", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "get_pawn_moves", "char", "position_t", "WHITE_KNIGHT", "bool", "__forloop_bishop_moves_gen", "BLACK_PAWN", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "BLACK_SHORT_CASTLE", "add_move_params", "BLACK_QUEEN", "add_move"], "used": ["min", "moves_init", "if", "moves_empty", "_add_move", "realloc", "assert", "moves_init_wcapacity", "moves_t", "int"]}, {"name": "rook.c", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["__forloop_rook_moves_gen", "get_rook_moves", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_queen_moves", "MOVE_PROMOTE_B", "moves_t", "int", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "get_pawn_moves", "char", "position_t", "WHITE_KNIGHT", "bool", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["get_rook_moves", "__forloop_rook_moves_gen"]}, {"name": "queen.c", "imports": ["stdint.h", "bitboard.h", "stdbool.h", "moves.h", "inttypes.h", "ints.h"], "symbols": ["get_queen_moves", "int", "char"], "unused": ["WHITE_SHORT_CASTLE", "WHITE_LONG_CASTLE", "blacks", "MOVE_SHORT_CASTLE", "MOVE_PROMOTE_R", "WHITE_QUEEN", "moves_init_wcapacity", "get_rook_moves", "MOVE_PROMOTE_B", "moves_t", "int", "__forloop_rook_moves_gen", "WHITE_BISHOP", "MOVE_PROMOTE_Q", "MOVE_EN_PASSANT", "get_king_moves", "BLACK_ROOK", "MOVE_LONG_CASTLE", "position_make_move", "WHITE_ROOK", "MOVE_CAPTURE", "PIECE_TYPE_COUNT", "assert_valid_position", "position_starting", "occupied_by", "add_move_params", "WHITE_KING", "MOVE_CHECK", "WHITE_TURN", "print_bitboard", "check_valid_position", "MOVE_PROMOTE_N", "whites", "get_knight_moves", "BLACK_KNIGHT", "BLACK_LONG_CASTLE", "BLACK_BISHOP", "BLACK_TURN", "move_t", "get_pawn_moves", "char", "position_t", "WHITE_KNIGHT", "bool", "moves_init", "__forloop_bishop_moves_gen", "get_bishop_moves", "WHITE_PAWN", "get_moves", "BLACK_KING", "moves_empty", "_add_move", "BLACK_SHORT_CASTLE", "BLACK_PAWN", "BLACK_QUEEN", "add_move"], "used": ["get_queen_moves"]}]
\ No newline at end of file diff --git a/symbol_analyzer/index.html b/symbol_analyzer/index.html new file mode 100644 index 0000000..3f0257b --- /dev/null +++ b/symbol_analyzer/index.html @@ -0,0 +1,137 @@ +<!DOCTYPE html> +<html> + <head> + <script src="./analysis.js"></script> + <style> +body { + background-color: #141514;4;4;4; +} + </style> + </head> + <body> + <canvas id="main" width="1000" height="1000" style="border:1px solid #fff;"> + </canvas> + <script> +const RADIUS = 20; +const WIDTH = 1000; +const HEIGHT = 1000; +const RING_RADIUS = Math.min(WIDTH, HEIGHT) / 2 - 2 * RADIUS; +const ignore_files = [ + "stdbool.h", + "queen.c", + "rook.c", + "king.c", + "pawn.c", + "bishop.c", + "knight.c" +]; + +data = data.filter(x => !ignore_files.includes(x.name)); + +const c = document.getElementById("main"); +const ctx = c.getContext("2d"); +ctx.textAlign = "center"; +ctx.font = "bold 10pt Courier"; + +function canvas_arrow(fromx, fromy, tox, toy) { + var headlen = 10; // length of head in pixels + var dx = tox - fromx; + var dy = toy - fromy; + var angle = Math.atan2(dy, dx); + ctx.moveTo( + fromx + Math.cos(angle) * RADIUS, + fromy + Math.sin(angle) * RADIUS + ); + ctx.lineTo( + tox + Math.cos(Math.PI + angle) * RADIUS, + toy + Math.sin(Math.PI + angle) * RADIUS + ); + ctx.lineTo( + tox - headlen * Math.cos(angle - Math.PI / 6) + Math.cos(Math.PI + angle) * RADIUS, + toy - headlen * Math.sin(angle - Math.PI / 6) + Math.sin(Math.PI + angle) * RADIUS + ); + ctx.moveTo( + tox + Math.cos(Math.PI + angle) * RADIUS, + toy + Math.sin(Math.PI + angle) * RADIUS + ); + ctx.lineTo( + tox - headlen * Math.cos(angle + Math.PI / 6) + Math.cos(Math.PI + angle) * RADIUS, + toy - headlen * Math.sin(angle + Math.PI / 6) + Math.sin(Math.PI + angle) * RADIUS + ); +} + +let mapping = {} + +for (let i = 0; i < data.length; i++) { + mapping[data[i].name] = i; + const angle = i * 2 * Math.PI / data.length; + const [x, y] = [ + RING_RADIUS * Math.cos(angle) + WIDTH / 2, + RING_RADIUS * Math.sin(angle) + HEIGHT / 2 + ]; + ctx.fillStyle = `hsl(${i * 255 / data.length}, 50%, 50%)`; + ctx.beginPath(); + ctx.arc(x, y, RADIUS, 0, 2 * Math.PI); + ctx.fill(); + ctx.fillStyle = "white"; + ctx.fillText(data[i].name, x, y); +} + +for (let i = 0; i < data.length; i++) { + for (let j = 0; j < data[i].imports.length; j++) { + if (!(data[i].imports[j] in mapping)) continue; + const to_idx = mapping[data[i].name]; + const from_idx = mapping[data[i].imports[j]]; + const from_angle = from_idx * 2 * Math.PI / data.length; + const [from_x, from_y] = [ + RING_RADIUS * Math.cos(from_angle) + WIDTH / 2, + RING_RADIUS * Math.sin(from_angle) + HEIGHT / 2 + ]; + const to_angle = to_idx * 2 * Math.PI / data.length; + const [to_x, to_y] = [ + RING_RADIUS * Math.cos(to_angle) + WIDTH / 2, + RING_RADIUS * Math.sin(to_angle) + HEIGHT / 2 + ]; + ctx.beginPath(); + ctx.strokeStyle = `hsl(${from_idx * 255 / data.length}, 50%, 40%)`; + canvas_arrow(from_x, from_y, to_x, to_y); + ctx.stroke(); + } +} + +function getCursorPosition(canvas, event) { + const rect = canvas.getBoundingClientRect() + const x = event.clientX - rect.left + const y = event.clientY - rect.top + return [x, y] +} + +const canvas = document.querySelector('canvas') +canvas.addEventListener('mousedown', function(e) { + const [x, y] = getCursorPosition(canvas, e) + for (let i = 0; i < data.length; i++) { + const angle = i * 2 * Math.PI / data.length; + const [point_x, point_y] = [ + RING_RADIUS * Math.cos(angle) + WIDTH / 2, + RING_RADIUS * Math.sin(angle) + HEIGHT / 2 + ]; + + + if (Math.pow(point_x - x, 2) + Math.pow(point_y - y, 2) > Math.pow(RADIUS, 2)) { + continue; + } + + console.clear() + console.log(data[i].symbols) + console.log(data[i].unused) + console.log(data[i].used) + // for (let j = 0; j < data[i].unused.length; j++) { + // console.log(data[i].unused[j]); + // } + // console.log(data[i].unused.length); + } +}) + + </script> + </body> +</html> diff --git a/symbol_analyzer/main.py b/symbol_analyzer/main.py index 1fa5457..f137cfb 100644 --- a/symbol_analyzer/main.py +++ b/symbol_analyzer/main.py @@ -1,26 +1,104 @@ +# this code was written to work, not to be maintained +# don't touch my trash + import os +import json from extractor import parse_file from parser import parse_definition_tokens from symbols import symbols_from_struct_tokens, symbols_from_enum_tokens -symbols = set() +stdlibs = [ + "stdlib.h", "assert.h", "stdio.h", "stdint.h", + "inttypes.h", "mman.h", "stdatomic.h", "string.h", "unistd.h", + "fcntl.h", "pthread.h" +] -for root, subdirs, files in os.walk("include"): - for file in files: - file_symbols = ["int", "bool", "char"] - definitions, usage = parse_file(root + "/" + file) - structs, enums, functions, typedefs = parse_definition_tokens( +files_content = { + "stdbool.h": { + "symbols": ["bool"], + "usage": [], + "imports": [] + } +} + +def handle(file): + files_content[file] = {} + file_symbols = ["int", "char"] + definitions, _ = parse_file(root + "/" + file) + structs, enums, functions, typedefs, imports, usage = \ + parse_definition_tokens( definitions, file_symbols ) - file_symbols.extend(symbols_from_struct_tokens(structs)) - file_symbols.extend(symbols_from_enum_tokens(enums)) - file_symbols.extend(functions) - file_symbols.extend(typedefs) - for item in file_symbols: - if item.isnumeric(): - continue - symbols.add(item) - -print(symbols) + file_symbols.extend(symbols_from_struct_tokens(structs)) + file_symbols.extend(symbols_from_struct_tokens(structs)) + file_symbols.extend(symbols_from_enum_tokens(enums)) + file_symbols.extend(functions) + file_symbols.extend(typedefs) + files_content[file]["symbols"] = set() + files_content[file]["imports"] = list(map(lambda x: x[1:-1] ,imports)) + files_content[file]["usage"] = usage + for item in file_symbols: + if item.isnumeric(): + continue + if "".join(item.split("_")).isalnum(): + files_content[file]["symbols"].add(item) + +for root, subdirs, files in os.walk("include"): + for file in files: + handle(file) +for root, subdirs, files in os.walk("src"): + for file in files: + handle(file) + +for file in files_content.keys(): + final_imports = set() + to_resolve = [] + for imported_file in files_content[file]["imports"]: + x = imported_file.split("/")[-1] + to_resolve.append(x) + final_imports.add(x) + + while len(to_resolve) > 0: + f = to_resolve.pop() + if f not in files_content: + if f not in stdlibs: + print(f) + assert f in stdlibs + continue + new_items = files_content[f]["imports"] + for new_item in new_items: + x = new_item.split("/")[-1] + to_resolve.append(x) + final_imports.add(x) + + files_content[file]["imports"] = final_imports + + +for file, file_content in files_content.items(): + symbols = list(file_content["symbols"]) + for imported_file in file_content["imports"]: + imported_file = imported_file.split("/")[-1] + if imported_file not in files_content: + assert imported_file in stdlibs + continue + symbols.extend(files_content[imported_file]["symbols"]) + symbols = set(symbols) + usage_set = set(file_content["usage"]) + files_content[file]["unused"] = symbols - usage_set + files_content[file]["used"] = symbols.intersection(usage_set) + +output = [] +for file in files_content.keys(): + output.append({ + "name": file, + "imports": list(files_content[file]["imports"]), + "symbols": list(files_content[file]["symbols"]), + "unused": list(files_content[file]["unused"]), + "used": list(files_content[file]["used"]) + }) + +with open("symbol_analyzer/analysis.js", "w") as f: + f.write("data = ") + json.dump(output, f) diff --git a/symbol_analyzer/parser.py b/symbol_analyzer/parser.py index 551857e..977a634 100644 --- a/symbol_analyzer/parser.py +++ b/symbol_analyzer/parser.py @@ -4,24 +4,29 @@ def parse_definition_tokens(tokens, symbols): structs = [] enums = [] functions = [] + imports = [] + usage = [] i = 0 while i < len(tokens): # skip comments if tokens[i] == "//": - while tokens[i] != "\n": + while tokens[i] != "\n" and i < len(tokens): i += 1 i += 1 continue - if tokens[i] == "typedef": + elif tokens[i] == "#include": + imports.append(tokens[i + 1]) + i += 2 + elif tokens[i] == "typedef": if tokens[i + 1] in symbols: simple_typedefs.append(tokens[i + 2]) i += 2 - if tokens[i] == "struct": + elif tokens[i] == "struct": i += 1 defs = [] depth = 0 - while True: + while i < len(tokens): if tokens[i] == "//": while tokens[i] != "\n": i += 1 @@ -37,7 +42,7 @@ def parse_definition_tokens(tokens, symbols): defs.append(tokens[i]) i += 1 structs.append(defs) - if tokens[i] == "enum": + elif tokens[i] == "enum": i += 1 defs = [] depth = 0 @@ -57,9 +62,15 @@ def parse_definition_tokens(tokens, symbols): defs.append(tokens[i]) i += 1 enums.append(defs) - i += 1 - - if tokens[i] == "(": + elif tokens[i] == "(": functions.append(tokens[i - 1]) + while tokens[i] != ")": + i += 1 + i += 1 + else: + usage.append(tokens[i]) + + i += 1 - return structs, enums, functions, simple_typedefs + print(structs, enums, functions, simple_typedefs, imports) + return structs, enums, functions, simple_typedefs, imports, usage |
