summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAargh Rai <aargh.rai+git@gmail.com>2026-07-13 21:58:18 +0530
committerAargh Rai <aargh.rai+git@gmail.com>2026-07-13 21:58:18 +0530
commitf8c0dc54e36cc201c657aa12e5a22029b092e1bc (patch)
treea0dd1a42c9681be98a7508c128db0dacacefc2e7 /src
parent2e8b78ab0ef01eaacd8094ff839ac93b4451e9c3 (diff)
restructed all the files + uci done now
also broke the symbol analyser in the process, i didn't help much, i had to pull out the pen & paper, but it made a cool graph never the less multithreading was a pain! but it got it in the end fixed the structs naming convention, if it's used outside by other files, it's typedeffed, otherwise it's not fixed the recursive imports issued i had in go_args*, where i was casting it to void* in uci to make it work now response.c doesn't deal with ipc, really happy with that change now every single thing has its own responsibility
Diffstat (limited to 'src')
-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
24 files changed, 858 insertions, 659 deletions
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");
+ }
+}
+