summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAargh Rai <aargh.rai+git@gmail.com>2026-07-07 23:37:41 +0530
committerAargh Rai <aargh.rai+git@gmail.com>2026-07-07 23:37:41 +0530
commit2761f8a533e2b025f209222a1e4ec70b91c7e8ee (patch)
treebb1ce2dfbf3f35fb81f8080776a7cc35e0ed3e3a
parent965bf81879b22a25fd9b0d17ce6defd3d51c6173 (diff)
thread spawning from the uci settings & best move & ponder is now sent
uci setup is ALMOST done, i can sense it
-rw-r--r--build.c2
-rw-r--r--src/engine.c144
-rw-r--r--src/ipc.h6
-rw-r--r--src/uci.c1
-rw-r--r--src/uci/response.c49
-rw-r--r--src/uci/state.h7
6 files changed, 173 insertions, 36 deletions
diff --git a/build.c b/build.c
index 5d64333..516c0ac 100644
--- a/build.c
+++ b/build.c
@@ -6,7 +6,7 @@
#include <time.h>
#include <string.h>
-#define CC "gcc", "-O3"
+#define CC "gcc"//, "-O3"
#define ENGINE_O "output/engine.o"
#define UCI_O "output/uci.o"
#define MAIN_O "output/main.o"
diff --git a/src/engine.c b/src/engine.c
index 944c0f4..a063520 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -10,38 +10,138 @@
#include "uci.h"
#include "ipc.h"
+// TODO: implement break conditions from the go command
+struct thread_args {
+ int id;
+ int stop;
+ position_t position;
+ struct engine_message *message;
+};
+void *engine_thread(void *_args) {
+ struct thread_args *args = (struct thread_args*)_args;
+
+ int k = 0;
+ while (k < 10) {
+ if (args->stop) continue;
+ struct engine_message *message = args->message;
+
+ k++;
+ message->depth = 69;
+ message->multipv = args->id;
+ message->pv = comm_moves_init();
+ add_comm_move(&message->pv, (struct uci_move) { 14, 24 });
+
+ if (k == 10) {
+ message->best_move = (struct uci_move) { 12, 24 };
+ message->ponder = (struct uci_move) { 42, 54 };
+ }
+
+ message->next = malloc(sizeof(struct engine_message*));
+ message->ready = 1;
+ args->message = message->next;
+ }
+}
+
+struct threads {
+ pthread_t *threads;
+ struct thread_args* args;
+ engine_messages *engine_messages;
+ size_t count;
+ size_t capacity;
+
+ position_t sharing_position;
+};
+
+void increase_threads(struct threads *threads, size_t change) {
+ if (threads->count + change > threads->capacity) {
+ threads->capacity = threads->count + change + 16; // TODO: maybe round it to the upper power of 2
+ }
+
+ threads->threads = threads->threads == NULL
+ ? malloc(sizeof(*threads->threads) * threads->capacity)
+ : realloc(threads->threads, sizeof(*threads->threads) * threads->capacity);
+
+ threads->args = threads->args == NULL
+ ? malloc(sizeof(*threads->args) * threads->capacity)
+ : realloc(threads->args, sizeof(*threads->args) * threads->capacity);
+
+ threads->engine_messages->data = threads->engine_messages->data == NULL
+ ? malloc(sizeof(*threads->engine_messages->data) * threads->capacity)
+ : realloc(
+ threads->engine_messages->data,
+ sizeof(*threads->engine_messages->data) * 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->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++) {
+ free(threads->engine_messages->data[threads->count - i - 1]);
+ 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);
+ }
+}
+
+// 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 = malloc(
- sizeof(*comms->engine_messages->data) * 1 // TODO: GET FROM UCI SETTINGS
- );
- comms->engine_messages->count = 1;
- comms->engine_messages->data[0] = malloc(sizeof(
- *comms->engine_messages->data[0]
- ));
- comms->engine_messages->data[0]->ready = 0;
-
- printf("ENGINE: %p\nENGINE MESSAGE: %p\n", comms, comms->engine_messages);
+ comms->uci_state_initialized = 0;
pthread_t uci_thread;
pthread_create(&uci_thread, NULL, &uci, (void*)comms);
- int k = 0;
+
+ while (atomic_load(&comms->uci_state_initialized) == 0);
+ comms->state.quit = 0;
+
+ struct threads engine_threads = {0};
+ engine_threads.engine_messages = comms->engine_messages;
+ int initialized = 0;
+
while (1) {
- if (k == 0) {
- struct engine_message *message = comms->engine_messages->data[0];
- message->depth = 69;
- message->pv = comm_moves_init();
- add_comm_move(&message->pv, (struct uci_move) { 14, 24 });
- message->next = malloc(sizeof(struct engine_message*));
- printf("\n%p\n", message->pv.moves);
-
- message->ready = 1;
- k++;
+ if (atomic_load(&comms->state.quit)) break;
+ if (!atomic_load(&comms->state.go)) continue;
+
+ if (initialized == 0) {
+ engine_threads.sharing_position = comms->state.position;
+ set_threads(&engine_threads, comms->state.threads);
+ initialized = 1;
}
}
+ set_threads(&engine_threads, 0);
+ free(engine_threads.threads);
+ free(engine_threads.args);
+ free(comms->engine_messages);
+ free(comms->engine_messages->data);
+ free(comms);
return 0;
}
diff --git a/src/ipc.h b/src/ipc.h
index 1c901b8..35b109b 100644
--- a/src/ipc.h
+++ b/src/ipc.h
@@ -29,6 +29,9 @@ struct engine_message {
int time;
comm_moves pv;
+ struct uci_move best_move;
+ struct uci_move ponder;
+
struct engine_message *next;
};
@@ -40,9 +43,8 @@ typedef struct {
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;
diff --git a/src/uci.c b/src/uci.c
index 9e3c8c7..fa9bf86 100644
--- a/src/uci.c
+++ b/src/uci.c
@@ -97,6 +97,7 @@ void *uci(void *_com) {
"<empty>",
&com->state.uci_setpositionvalue
);
+ atomic_store(&com->uci_state_initialized, 1);
ucicmd cmd = ucicmd_init();
size_t n;
diff --git a/src/uci/response.c b/src/uci/response.c
index dbf4614..6208a54 100644
--- a/src/uci/response.c
+++ b/src/uci/response.c
@@ -154,10 +154,22 @@ void handle_idle(
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");
+ 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;
+ }
+ state->position = fen.position;
}
else if (strcmp(mode, "fen") == 0) {
- state->position = load_fen(ucicmd_get_arg(cmd, k++));
+ struct fen_load fen = load_fen(ucicmd_get_arg(cmd, k++));
+ if (fen.failed) {
+ printf("info invalid fen\n");
+ return;
+ }
+ state->position = fen.position;
} else { assert(0); }
if (cmd.args_count >= k) return;
@@ -185,7 +197,6 @@ void handle_idle(
(move[2] - 'a') * 8 + (move[3] - '1')
};
}
- state->go = 1;
} else if (strcmp(cmd.root, "stop") == 0) {
} else if (strcmp(cmd.root, "quit") == 0) {
free(cmd.args);
@@ -197,10 +208,11 @@ void handle_idle(
free(setting.value.string->data);
}
- exit(0);
+ atomic_store(&state->quit, 1);
} else if (strcmp(cmd.root, "isready") == 0) {
current_state = STATE_SYNC;
} else if (strcmp(cmd.root, "go") == 0) {
+ atomic_store(&state->go, 1);
current_state = STATE_ACTIVE;
} else {
printf("info violation\n");
@@ -238,7 +250,6 @@ void handle_active(
for (int i = 0; i < engine_messages->count; i++) {
struct engine_message *old = engine_messages->data[i];
if (!old->ready) continue;
- printf("INITIALIZED\n");
old->ready = 0;
printf(
@@ -265,10 +276,30 @@ void handle_active(
);
}
printf("\n");
- // // info depth 1 seldepth 1 multipv 1 score cp 18 nodes 20 nps 4000 hashfull 0 tbhits 0 time 5 pv e2e4
- //
- // engine_messages->data[i] = old->next;
- // free(old);
+
+ if (old->best_move.from != 0 && old->best_move.to != 0) {
+ 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);
}
// TODO: this section will call the engine to analysis
if (cmd.empty) {
diff --git a/src/uci/state.h b/src/uci/state.h
index 9b09774..9c59a3a 100644
--- a/src/uci/state.h
+++ b/src/uci/state.h
@@ -1,6 +1,7 @@
#ifndef UCI_STATE_H
#define UCI_STATE_H
+#include <stdatomic.h>
#include "../fen.h"
typedef struct {
@@ -80,8 +81,10 @@ typedef struct {
char author[32];
bool debug;
- int go;
- struct fen_load position;
+ atomic_int go;
+ atomic_int quit;
+
+ position_t position;
struct uci_move *moves;
int moves_count;