From f8c0dc54e36cc201c657aa12e5a22029b092e1bc Mon Sep 17 00:00:00 2001 From: Aargh Rai Date: Mon, 13 Jul 2026 21:58:18 +0530 Subject: 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 --- assets/board.js | 262 ------------------------------ assets/pieces/bb.webp | Bin 538 -> 0 bytes assets/pieces/bk.webp | Bin 1028 -> 0 bytes assets/pieces/bn.webp | Bin 740 -> 0 bytes assets/pieces/bp.png | Bin 692 -> 0 bytes assets/pieces/bq.png | Bin 1563 -> 0 bytes assets/pieces/br.webp | Bin 274 -> 0 bytes assets/pieces/wb.webp | Bin 834 -> 0 bytes assets/pieces/wk.webp | Bin 946 -> 0 bytes assets/pieces/wn.png | Bin 1263 -> 0 bytes assets/pieces/wp.png | Bin 898 -> 0 bytes assets/pieces/wq.webp | Bin 1388 -> 0 bytes assets/pieces/wr.png | Bin 748 -> 0 bytes build.c | 12 +- include/engine/moves.h | 36 +++-- include/engine/threads.h | 53 +++++++ include/ipc.h | 78 --------- include/ipc/engine_message.h | 67 ++++++++ include/ipc/go_args.h | 25 +++ include/ipc/moves.h | 19 +++ include/ipc/state.h | 42 +++++ include/ipc/threads.h | 9 ++ include/ipc/uci.h | 9 ++ include/uci.h | 8 - include/uci/command.h | 21 --- include/uci/internals/command.h | 21 +++ include/uci/internals/response.h | 24 +++ include/uci/response.h | 24 --- include/uci/state.h | 77 +++++---- justfile | 7 + src/bitboard.c | 2 +- src/engine.c | 200 +---------------------- src/engine/moves.c | 2 +- src/engine/moves/bishop.c | 3 +- src/engine/moves/king.c | 6 +- src/engine/moves/knight.c | 3 +- src/engine/moves/pawn.c | 3 +- src/engine/moves/queen.c | 3 +- src/engine/moves/rook.c | 3 +- src/engine/moves/vec.c | 3 +- src/engine/thread.c | 34 ++++ src/engine/threads.c | 91 +++++++++++ src/fen.c | 1 - src/ipc.c | 51 +----- src/ipc/engine_message.c | 127 +++++++++++++++ src/ipc/go_args.c | 19 +++ src/ipc/moves.c | 23 +++ src/ipc/state.c | 41 +++++ src/ipc/threads.c | 8 + src/main.c | 90 +++++++++++ src/uci.c | 196 +++++++++++++---------- src/uci/command.c | 52 +++--- src/uci/response.c | 333 +++++++++------------------------------ src/uci/state.c | 223 +++++++++++++++++++++----- symbol_analyzer/analysis.js | 1 + symbol_analyzer/index.html | 137 ++++++++++++++++ symbol_analyzer/main.py | 110 +++++++++++-- symbol_analyzer/parser.py | 29 ++-- 58 files changed, 1455 insertions(+), 1133 deletions(-) delete mode 100644 assets/board.js delete mode 100644 assets/pieces/bb.webp delete mode 100644 assets/pieces/bk.webp delete mode 100644 assets/pieces/bn.webp delete mode 100644 assets/pieces/bp.png delete mode 100644 assets/pieces/bq.png delete mode 100644 assets/pieces/br.webp delete mode 100644 assets/pieces/wb.webp delete mode 100644 assets/pieces/wk.webp delete mode 100644 assets/pieces/wn.png delete mode 100644 assets/pieces/wp.png delete mode 100644 assets/pieces/wq.webp delete mode 100644 assets/pieces/wr.png create mode 100644 include/engine/threads.h delete mode 100644 include/ipc.h create mode 100644 include/ipc/engine_message.h create mode 100644 include/ipc/go_args.h create mode 100644 include/ipc/moves.h create mode 100644 include/ipc/state.h create mode 100644 include/ipc/threads.h create mode 100644 include/ipc/uci.h delete mode 100644 include/uci.h delete mode 100644 include/uci/command.h create mode 100644 include/uci/internals/command.h create mode 100644 include/uci/internals/response.h delete mode 100644 include/uci/response.h create mode 100644 justfile create mode 100644 src/engine/thread.c create mode 100644 src/engine/threads.c create mode 100644 src/ipc/engine_message.c create mode 100644 src/ipc/go_args.c create mode 100644 src/ipc/moves.c create mode 100644 src/ipc/state.c create mode 100644 src/ipc/threads.c create mode 100644 src/main.c create mode 100644 symbol_analyzer/analysis.js create mode 100644 symbol_analyzer/index.html 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 deleted file mode 100644 index f780b4d..0000000 Binary files a/assets/pieces/bb.webp and /dev/null differ diff --git a/assets/pieces/bk.webp b/assets/pieces/bk.webp deleted file mode 100644 index 23d2e3b..0000000 Binary files a/assets/pieces/bk.webp and /dev/null differ diff --git a/assets/pieces/bn.webp b/assets/pieces/bn.webp deleted file mode 100644 index 68a6d63..0000000 Binary files a/assets/pieces/bn.webp and /dev/null differ diff --git a/assets/pieces/bp.png b/assets/pieces/bp.png deleted file mode 100644 index fa57435..0000000 Binary files a/assets/pieces/bp.png and /dev/null differ diff --git a/assets/pieces/bq.png b/assets/pieces/bq.png deleted file mode 100644 index 6334dd4..0000000 Binary files a/assets/pieces/bq.png and /dev/null differ diff --git a/assets/pieces/br.webp b/assets/pieces/br.webp deleted file mode 100644 index 8d078e1..0000000 Binary files a/assets/pieces/br.webp and /dev/null differ diff --git a/assets/pieces/wb.webp b/assets/pieces/wb.webp deleted file mode 100644 index 5020e5e..0000000 Binary files a/assets/pieces/wb.webp and /dev/null differ diff --git a/assets/pieces/wk.webp b/assets/pieces/wk.webp deleted file mode 100644 index 72fdcf7..0000000 Binary files a/assets/pieces/wk.webp and /dev/null differ diff --git a/assets/pieces/wn.png b/assets/pieces/wn.png deleted file mode 100644 index a03ccac..0000000 Binary files a/assets/pieces/wn.png and /dev/null differ diff --git a/assets/pieces/wp.png b/assets/pieces/wp.png deleted file mode 100644 index d968278..0000000 Binary files a/assets/pieces/wp.png and /dev/null differ diff --git a/assets/pieces/wq.webp b/assets/pieces/wq.webp deleted file mode 100644 index bfbd57a..0000000 Binary files a/assets/pieces/wq.webp and /dev/null differ diff --git a/assets/pieces/wr.png b/assets/pieces/wr.png deleted file mode 100644 index 69811d8..0000000 Binary files a/assets/pieces/wr.png and /dev/null differ diff --git a/build.c b/build.c index cd2d376..8f799b5 100644 --- a/build.c +++ b/build.c @@ -7,15 +7,15 @@ #include #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 +#include + +#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 -#include - -#include "fen.h" -#include "uci/state.h" - -typedef struct { - struct uci_move *moves; - int count; - int capacity; -} comm_moves; - -struct engine_message { - int id; - - int ready; - - int depth; - int seldepth; - int multipv; - int score_cp; - int nodes; - int nps; - int hashfull; - int tbhits; - int time; - - int mate; - bool node_limit; - comm_moves pv; - - struct uci_move best_move; - struct uci_move ponder; - - struct engine_message *next; -}; - -typedef struct { - struct engine_message **data; - int count; -} engine_messages; - -enum { MESSAGE_FILLED, MESSAGE_READ, MESSAGE_PROCESSED }; -typedef struct { - engine_messages *engine_messages; - uci_state state; - int uci_state_initialized; - int uci_message_ready; - struct fen_load from_position; - comm_moves moves; -} comms; - -comm_moves comm_moves_init(); -void add_comm_move(comm_moves *moves, struct uci_move move); - -struct go_args { - comm_moves searchmoves; - bool ponder; - int wtime; - int btime; - int winc; - int binc; - int movestogo; - int depth; - int nodes; - int mate; - int movetime; - bool infinite; - int perft; -}; -bool should_continue(struct engine_message *message, struct go_args* go); - -#endif // IPC_H diff --git a/include/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 + +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 + +#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 -#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 -#include #include 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 -#include -#include -#include -#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 +#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 #include 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 + +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 +#include +#include +#include + +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]; +} diff --git a/src/fen.c b/src/fen.c index cdbee49..7c7c8e3 100644 --- a/src/fen.c +++ b/src/fen.c @@ -1,4 +1,3 @@ -#include #include #include "fen.h" diff --git a/src/ipc.c b/src/ipc.c index 5caf71e..f8b9a00 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -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 +#include + +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 + +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 + +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 +#include + +#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 +#include +#include +#include +#include +#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" diff --git a/src/uci.c b/src/uci.c index 6a2c412..cc16954 100644 --- a/src/uci.c +++ b/src/uci.c @@ -1,18 +1,17 @@ -#include #include -#include #include #include #include +#include +#include -#include -#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 ", 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", - "", - &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", - "", - &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 #include #include -#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 #include -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 #include -#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 -#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 ", 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", + "", + &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", + "", + &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 @@ + + + + + + + + + + + + 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 -- cgit v1.2.3