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