diff options
| author | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-05 23:55:45 +0530 |
|---|---|---|
| committer | Aargh Rai <aargh.rai+git@gmail.com> | 2026-07-05 23:55:45 +0530 |
| commit | 1876294f217d7faa2a07dbaaaab82d142ce42803 (patch) | |
| tree | d67ba4b240f25042063c06ce99370e3be34457ff | |
| parent | f17df9538b1c3f58f12b738083b747ac332b8d71 (diff) | |
all in on uci
the old server.c & log.c is gonna be removed soon
| -rw-r--r-- | .clangd | 4 | ||||
| -rw-r--r-- | bitboards.html | 111 | ||||
| -rw-r--r-- | board.html | 99 | ||||
| -rw-r--r-- | build.c | 50 | ||||
| -rw-r--r-- | shell.nix | 2 | ||||
| -rw-r--r-- | src/engine.c | 7 | ||||
| -rw-r--r-- | src/ipc.c | 142 | ||||
| -rw-r--r-- | src/uci.c | 18 | ||||
| -rw-r--r-- | src/uci/response.c | 67 | ||||
| -rw-r--r-- | src/uci/state.h | 9 |
10 files changed, 194 insertions, 315 deletions
diff --git a/.clangd b/.clangd deleted file mode 100644 index a5e5c6b..0000000 --- a/.clangd +++ /dev/null @@ -1,4 +0,0 @@ -CompileFlags: - Add: [-Wno-override-init] - Compiler: arm-none-eabi-gcc - diff --git a/bitboards.html b/bitboards.html deleted file mode 100644 index 8323dfe..0000000 --- a/bitboards.html +++ /dev/null @@ -1,111 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Bitboard editor</title> - <style> - :root { - --square-side-length: 6rem; - --dark-color: #779556; - --light-color: #ebecd0; - --selected-color: #f37f6b; - --background-color: #0f0f0f; - --text-color: #fefefe; - } - body { - display: flex; - flex-direction: column; - align-items: center; - background-color: var(--background-color); - color: var(--text-color); - } - #board { - display: grid; - grid-template-columns: repeat(9, 1fr); - grid-template-rows: repeat(9, 1fr); - } - .dark { - background-color: var(--dark-color); - } - .light { - background-color: var(--light-color); - } - .selected { - background-color: var(--selected-color); - } - .square { - width: var(--square-side-length); - height: var(--square-side-length); - } - .label { - width: var(--square-side-length); - height: var(--square-side-length); - display: flex; - align-items: center; - justify-content: flex-end; - } - .horizontal_label { - width: var(--square-side-length); - height: var(--square-side-length); - display: flex; - justify-content: center; - } - </style> -</head> -<body> - <div id="board"> - </div> - <div id="output"> - </div> - <script> - const output = document.getElementById("output"); - - let bitboard = 0n; - function trackBitboard(i, selected) { - const mask = 1n << BigInt(i); - if (selected) { - bitboard |= mask; - } else { - bitboard &= ~mask; - } - output.textContent = bitboard.toString(); - } - - const selectedAction = trackBitboard; - - 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 shift = Math.floor(i / 8); - square.classList.add((i + shift) % 2 ? "dark" : "light"); - square.onclick = () => { - const selected = square.classList.contains("selected"); - selectedAction((i % 8) - 8 * Math.floor(i / 8) + 56, !selected); - if (selected) { - square.classList.remove("selected"); - } else { - square.classList.add("selected"); - } - }; - 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); - } - </script> -</body> -</html> diff --git a/board.html b/board.html deleted file mode 100644 index d7ae9da..0000000 --- a/board.html +++ /dev/null @@ -1,99 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Board</title> - <style> - :root { - --square-side-length: 6rem; - --dark-color: #779556; - --light-color: #ebecd0; - --selected-color: #f37f6b; - --background-color: #0f0f0f; - --text-color: #fefefe; - } - body { - display: flex; - flex-direction: column; - align-items: center; - background-color: var(--background-color); - color: var(--text-color); - } - #board { - display: grid; - grid-template-columns: repeat(9, 1fr); - grid-template-rows: repeat(9, 1fr); - } - .dark { - background-color: var(--dark-color); - } - .light { - background-color: var(--light-color); - } - .selected { - background-color: var(--selected-color); - } - .rendering_marker { - width: 2rem; - height: 2rem; - border-radius: 50%; - } - .possible_move { - background-color: #0f0f0f55; - } - .square { - width: var(--square-side-length); - height: var(--square-side-length); - background-size: cover; - display: flex; - justify-content: center; - align-items: center; - } - .label { - width: var(--square-side-length); - height: var(--square-side-length); - display: flex; - align-items: center; - justify-content: flex-end; - } - .horizontal_label { - width: var(--square-side-length); - height: var(--square-side-length); - display: flex; - justify-content: center; - } - #mouse { - position: absolute; - width: var(--square-side-length); - height: var(--square-side-length); - transform: translate(-50%, -50%); - transition: 0.1s ease out; - pointer-events: none; - background-size: cover; - } - button { - border: none; - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - margin-bottom: 2rem; - cursor: pointer; - } - button:hover { - opacity: 0.9; - } - </style> - <script src="./assets/board.js"></script> -</head> -<body> - <button onclick="connectSocket()">Reconnect</button> - <div id="board"> - </div> - <div id="output"> - </div> - <div id="mouse"> - </div> -</body> -</html> @@ -31,8 +31,6 @@ void print_cmd(char** args) { int clean_mode(int run_mode); int test_mode(int run_mode); -int server_mode(int run_mode); -int engine_mode(int run_mode); int uci_mode(int run_mode); // https://github.com/tsoding/nob.h/blob/0a08926d8094fc4ae678155c5d73ae21d1f96f3f/nob.h#L2413 @@ -54,11 +52,7 @@ int needs_rebuild(char* bin_file, char* source_file) { } #define ENGINE_O "output/engine.o" -#define SERVER_O "output/server.o" #define UCI_O "output/uci.o" -#define LOG_O "output/log.o" - -#define LOGGER_C "src/logger/logger.c" int main(int argc, char** argv) { if (needs_rebuild(argv[0], __FILE__)) { @@ -82,16 +76,7 @@ int main(int argc, char** argv) { if (strcmp(argv[1], "clean") == 0) { return clean_mode(run_mode); } - if (strcmp(argv[1], "uci") == 0) { - return uci_mode(run_mode); - } - RUN_CMD({CC, "src/log.c", "-o", LOG_O, NULL}); - if (strcmp(argv[1], "engine") == 0) { - return engine_mode(run_mode); - } - if (strcmp(argv[1], "server") == 0) { - return server_mode(run_mode); - } + return uci_mode(run_mode); } int clean_mode(int _) { @@ -108,36 +93,10 @@ int test_mode(int run_mode) { execvp(args[0], args); } - RUN_CMD({CC, "generate/find_tests.c", LOGGER_C, "-o", "output/find_tests.o", NULL}); + RUN_CMD({CC, "generate/find_tests.c", "-o", "output/find_tests.o", NULL}); RUN_CMD({"./output/find_tests.o", NULL}); printf("\n"); - RUN_CMD({CC, "tests/main.c", LOGGER_C, "-o", "output/test.o", NULL}); - return status != 0; -} - -int server_mode(int run_mode) { - if (run_mode) { - RUN_CMD({"rm", "/dev/mqueue/logs", NULL}); - RUN_CMD({"rm", "/dev/mqueue/server_to_engine", "/dev/mqueue/engine_to_server", NULL}); - char* args[] = {LOG_O, SERVER_O, ENGINE_O, NULL}; - print_cmd(args); - execvp(args[0], args); - } - - RUN_CMD({CC, "src/server.c", LOGGER_C, "-lcrypto", "-o", SERVER_O, NULL}); - RUN_CMD({CC, "src/engine.c", LOGGER_C, "-o", ENGINE_O, NULL}); - return status != 0; -} - -int engine_mode(int run_mode) { - if (run_mode) { - RUN_CMD({"rm", "/dev/mqueue/logs", NULL}); - char* args[] = {LOG_O, ENGINE_O, NULL}; - print_cmd(args); - execvp(args[0], args); - } - - RUN_CMD({CC, "src/engine.c", LOGGER_C, "-o", ENGINE_O, NULL}); + RUN_CMD({CC, "tests/main.c", "-o", "output/test.o", NULL}); return status != 0; } @@ -148,6 +107,7 @@ int uci_mode(int run_mode) { execvp(args[0], args); } - RUN_CMD({CC, "src/uci.c", "-o", UCI_O, NULL}); + RUN_CMD({CC, "src/engine.c", "-o", ENGINE_O, NULL}); + RUN_CMD({CC, "src/uci.c", "-o", UCI_O, ENGINE_O, NULL}); return status != 0; } @@ -1,6 +1,6 @@ { pkgs ? import <nixpkgs> {} }: let - install_opt_deps = false; + install_opt_deps = true; libraries = with pkgs; [ webkitgtk_4_1 gtk3 diff --git a/src/engine.c b/src/engine.c index 1ff4fef..3c64cce 100644 --- a/src/engine.c +++ b/src/engine.c @@ -6,9 +6,6 @@ #include "fcntl.h" #include "ipc.c" -#define LOG_MODULE "engine" -#include "logger/logger.h" - struct sqrstr { char data[2]; }; @@ -18,10 +15,6 @@ struct sqrstr sqr_to_str(int i) { } int main(void) { - mqd_t logging = mq_open("/logs", O_WRONLY); - mqd_t tx = mq_open("/engine_to_server", O_WRONLY); - mqd_t rx = mq_open("/server_to_engine", O_RDONLY); - while (1) { char* x = read_queue(rx); log_infof("Received: %s", x); @@ -1,41 +1,133 @@ #ifndef IPC_C #define IPC_C -#include <mqueue.h> -#include <stdio.h> #include <stdlib.h> +#include <sys/mman.h> -struct mq_attr attr = { - .mq_flags = 0, - .mq_maxmsg = 10, - .mq_msgsize = 1024, - .mq_curmsgs = 0, -}; - -char* read_queue(mqd_t target) { - char* buf = malloc(attr.mq_msgsize); - int n = mq_receive(target, buf, attr.mq_msgsize, NULL); - if (n == -1) { - perror("mq_receive"); - free(buf); - return NULL; +#include "engine/fen.h" + +typedef struct { + struct uci_move *moves; + int count; + int capacity; +} comm_moves; + +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)); } - return buf; + moves->moves[moves->count++] = move; } -void send_queue(mqd_t target, const char* msg, int n) { - mq_send(target, msg, n, 0); +typedef struct { + bool engine_message_ready; + int depth; + int seldepth; + int multipv; + int score_cp; + int nodes; + int nps; + int hashfull; + int tbhits; + int time; + comm_moves pv; + + bool uci_message_ready; + struct fen_load from_position; + comm_moves moves; +} comms; + +// https://stackoverflow.com/a/5656561 +comms* create_shared_memory() { + int protection = PROT_READ | PROT_WRITE; + int visibility = MAP_SHARED | MAP_ANONYMOUS; + comms* state = (comms*)mmap( + NULL, + sizeof(comms), + protection, visibility, + -1, 0 + ); + state->engine_message_ready = false; + state->depth = 0; + state->seldepth = 0; + state->multipv = 0; + state->score_cp = 0; + state->nodes = 0; + state->nps = 0; + state->hashfull = 0; + state->tbhits = 0; + state->time = 0; + state->pv = (comm_moves) { + (comms*)mmap( + NULL, + sizeof(struct uci_move) * 50, + protection, visibility, + -1, 0 + ), 0, 50 + }; + state->uci_message_ready = false; + state->from_position = {0}; + state->moves = (comm_moves) { + (comms*)mmap( + NULL, + sizeof(struct uci_move) * 50, + protection, visibility, + -1, 0 + ), 0, 50 + }; + + return state; } -int get_num_messages(mqd_t target) { - struct mq_attr target_attr; +void send_uci_message( + comms *comms, + struct fen_load from_position +) { + comms->from_position = from_position; + comms->uci_message_ready = true; +} - if (mq_getattr(target, &target_attr) == -1) { - perror("mq_getattr"); - exit(1); +void send_engine_message( + comms *comms, + int depth, + int seldepth, + int multipv, + int score_cp, + int nodes, + int nps, + int hashfull, + int tbhits, + int time +) { + comms->depth = depth; + comms->seldepth = seldepth; + comms->multipv = multipv; + comms->score_cp = score_cp; + comms->nodes = nodes; + comms->nps = nps; + comms->hashfull = hashfull; + comms->tbhits = tbhits; + comms->time = time; + comms->engine_message_ready = true; +} + +bool receive_uci_message(comms *comms) { + if (comms->uci_message_ready) { + comms->uci_message_ready = false; + return true; } + return false; +} - return target_attr.mq_curmsgs; +// TODO: think about dealing with multiple engine messages +bool receive_engine_message(comms *comms) { + if (comms->engine_message_ready) { + comms->engine_message_ready = false; + return true; + } + return false; } + #endif // IPC_C @@ -32,7 +32,7 @@ void load_from_message(ucicmd* cmd, const char* message) { ucicmd_add(cmd, token); } -int main() { +int main(int argc, char** argv) { // https://stackoverflow.com/a/41559081 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); @@ -54,42 +54,42 @@ int main() { "Clear Hash", &state.clear_hash ); - state.option_settings[k++] = option_setting_check( + state.option_settings[k++] = option_setting_check( "UCI_ShowCurrLine", false, &state.uci_showcurrline ); - state.option_settings[k++] = option_setting_check( + state.option_settings[k++] = option_setting_check( "UCI_ShowRefutations", false, &state.uci_showrefutations ); - state.option_settings[k++] = option_setting_check( + state.option_settings[k++] = option_setting_check( "UCI_LimitStrength", false, &state.uci_limitstrength ); - state.option_settings[k++] = option_setting_spin( + state.option_settings[k++] = option_setting_spin( "UCI_Elo", 100, 3500, 800, &state.uci_elo ); - state.option_settings[k++] = option_setting_check( + state.option_settings[k++] = option_setting_check( "UCI_AnalyseMode", false, &state.uci_analysemode ); - state.option_settings[k++] = option_setting_string( + state.option_settings[k++] = option_setting_string( "UCI_Opponent", "<empty>", &state.uci_opponent ); - state.option_settings[k++] = option_setting_string( + state.option_settings[k++] = option_setting_string( "UCI_EngineAbout", "Gacrux by Aargh Rai, Checkout https://git.aarghrai.com/gacrux", &state.uci_engineabout ); - state.option_settings[k++] = option_setting_string( + state.option_settings[k++] = option_setting_string( "UCI_SetPositionValue", "<empty>", &state.uci_setpositionvalue diff --git a/src/uci/response.c b/src/uci/response.c index 9b3118b..a7e53fd 100644 --- a/src/uci/response.c +++ b/src/uci/response.c @@ -1,7 +1,10 @@ #include <string.h> #include <assert.h> #include <stdlib.h> + #include "response.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); @@ -33,7 +36,9 @@ void apply_option(uci_state *state, char *name, char *buffer) { } else { assert(0); } return; } - printf("invalid option\n"); + if (state->debug) { + printf("debug: invalid option\n"); + } } // examples from uci_min.txt @@ -79,10 +84,6 @@ enum { }; int current_state = STATE_INITIAL; -void todo() { - assert(0); -} - void handle_uci(uci_state *state, ucicmd cmd) { if (current_state == STATE_INITIAL) { return handle_initial(state, cmd); @@ -104,12 +105,14 @@ void handle_uci(uci_state *state, ucicmd cmd) { void handle_initial(uci_state *state, ucicmd 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); printf("id author %s\n", state->author); int settings_count = sizeof(state->option_settings)/sizeof(option_setting_t); for (int i = 0; i < settings_count; i++) { print_setting(state->option_settings[i]); } + // --- printf("uciok\n"); current_state = STATE_IDLE; } @@ -136,35 +139,69 @@ void handle_idle(uci_state *state, ucicmd cmd) { *(--cursor) = 0; apply_option(state, name, buffer); } else if (strcmp(cmd.root, "ucinewgame") == 0) { + // clear game state here } else if (strcmp(cmd.root, "position") == 0) { + int k = 0; + char* mode = ucicmd_get_arg(cmd, 0); + if (strcmp(mode, "startpos") == 0) { + state->position = load_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); + } + else if (strcmp(mode, "fen") == 0) { + state->position = load_fen(ucicmd_get_arg(cmd, k++)); + } else { assert(0); } + + if (cmd.args_count >= k) return; + assert(ucicmd_get_arg(cmd, k++), "moves") == 0); + struct uci_move *moves = malloc((cmd.args_count - k) * sizeof(struct uci_move)); + int l = 0; + for (; k < cmd.args_count; k++) { + char* move = ucicmd_get_arg(cmd, k); + moves[l++] = (struct uci_move) { + (move[0] - 'a') * 8 + (move[1] - '1'), + (move[2] - 'a') * 8 + (move[3] - '1') + }; + } + // SENT state->position & struct uci_move to ENGINE } else if (strcmp(cmd.root, "stop") == 0) { } else if (strcmp(cmd.root, "quit") == 0) { free(cmd.args); + + 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 (OPTION_STRING != setting.type) continue; + free(setting.value.string->data); + } + exit(0); } else if (strcmp(cmd.root, "isready") == 0) { current_state = STATE_SYNC; } else if (strcmp(cmd.root, "go") == 0) { current_state = STATE_ACTIVE; } else { - printf("Invalid command: %s\n", cmd.root); + printf("info violation\n"); } } void handle_sync(uci_state *state, ucicmd cmd) { - // when i come up with some info to give: - // printf("info\n"); + // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 5 SECONDS + + + + // --- printf("readyok\n"); current_state = STATE_IDLE; } void handle_ping(uci_state *state, ucicmd cmd) { - // when i come up with some info to give: - // printf("info\n"); - // + // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 1 SECONDS + // if (TODO) { // printf("bestmove\n"); // current_state = STATE_IDLE; // } + + // --- printf("readyok\n"); current_state = STATE_ACTIVE; } @@ -179,13 +216,15 @@ void handle_active(uci_state *state, ucicmd cmd) { } else if (strcmp(cmd.root, "stop") == 0) { current_state = STATE_HALT; } else { - printf("Invalid command: %s\n", cmd.root); + printf("info violation\n"); } } void handle_halt(uci_state *state, ucicmd cmd) { - // when i come up with some info to give: - // printf("info\n"); + // TIMEOUT NOTICE: THE FOLLOWING BLOCK SHOULDN'T TAKE MORE THAN 1 SECONDS + + + // --- printf("bestmove 0000\n"); // TODO: idk get it rn current_state = STATE_IDLE; } diff --git a/src/uci/state.h b/src/uci/state.h index fd24b7e..cb0d63f 100644 --- a/src/uci/state.h +++ b/src/uci/state.h @@ -1,6 +1,8 @@ #ifndef UCI_STATE_H #define UCI_STATE_H +#include "engine/fen.h" + typedef struct { char* data; int length; @@ -78,6 +80,8 @@ typedef struct { char author[32]; bool debug; + struct fen_load position; + option_setting_t option_settings[11]; // options @@ -100,4 +104,9 @@ typedef struct { str_t uci_setpositionvalue; } uci_state; +struct uci_move { + int from; + int to; +}; + #endif // UCI_STATE_H |
