diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bitboard.c | 2 | ||||
| -rw-r--r-- | src/engine.c | 200 | ||||
| -rw-r--r-- | src/engine/moves.c | 2 | ||||
| -rw-r--r-- | src/engine/moves/bishop.c | 3 | ||||
| -rw-r--r-- | src/engine/moves/king.c | 6 | ||||
| -rw-r--r-- | src/engine/moves/knight.c | 3 | ||||
| -rw-r--r-- | src/engine/moves/pawn.c | 3 | ||||
| -rw-r--r-- | src/engine/moves/queen.c | 3 | ||||
| -rw-r--r-- | src/engine/moves/rook.c | 3 | ||||
| -rw-r--r-- | src/engine/moves/vec.c | 3 | ||||
| -rw-r--r-- | src/engine/thread.c | 34 | ||||
| -rw-r--r-- | src/engine/threads.c | 91 | ||||
| -rw-r--r-- | src/fen.c | 1 | ||||
| -rw-r--r-- | src/ipc.c | 51 | ||||
| -rw-r--r-- | src/ipc/engine_message.c | 127 | ||||
| -rw-r--r-- | src/ipc/go_args.c | 19 | ||||
| -rw-r--r-- | src/ipc/moves.c | 23 | ||||
| -rw-r--r-- | src/ipc/state.c | 41 | ||||
| -rw-r--r-- | src/ipc/threads.c | 8 | ||||
| -rw-r--r-- | src/main.c | 90 | ||||
| -rw-r--r-- | src/uci.c | 196 | ||||
| -rw-r--r-- | src/uci/command.c | 52 | ||||
| -rw-r--r-- | src/uci/response.c | 333 | ||||
| -rw-r--r-- | src/uci/state.c | 223 |
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]; +} @@ -1,4 +1,3 @@ -#include <assert.h> #include <stdbool.h> #include "fen.h" @@ -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" @@ -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"); + } +} + |
