#include #include #include #include "response.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; } printf("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 todo() { assert(0); } void handle_uci(uci_state *state, ucicmd cmd) { if (current_state == STATE_INITIAL) { return handle_initial(state, cmd); } if (current_state == STATE_IDLE) { return handle_idle(state, cmd); } if (current_state == STATE_SYNC) { return handle_sync(state, cmd); } if (current_state == STATE_PING) { return handle_ping(state, cmd); } if (current_state == STATE_ACTIVE) { return handle_active(state, cmd); } return handle_halt(state, cmd); } void handle_initial(uci_state *state, ucicmd cmd) { if (cmd.empty || strcmp(cmd.root, "uci") != 0) return; printf("id name %s\n", state->name); printf("id author %s\n", state->author); int settings_count = sizeof(state->option_settings)/sizeof(option_setting_t); for (int i = 0; i < settings_count; i++) { print_setting(state->option_settings[i]); } printf("uciok\n"); current_state = STATE_IDLE; } void handle_idle(uci_state *state, ucicmd cmd) { if (cmd.empty) return; if (strcmp(cmd.root, "debug") == 0) { state->debug = strcmp(ucicmd_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); if (strcmp(arg, "value") == 0) { *(--cursor) = 0; cursor = buffer; continue; } cursor = stpncpy(cursor, arg, MAX_TOKEN_SIZE); *(cursor++) = ' '; } *(--cursor) = 0; apply_option(state, name, buffer); } else if (strcmp(cmd.root, "ucinewgame") == 0) { } else if (strcmp(cmd.root, "position") == 0) { } else if (strcmp(cmd.root, "stop") == 0) { } else if (strcmp(cmd.root, "quit") == 0) { free(cmd.args); exit(0); } else if (strcmp(cmd.root, "isready") == 0) { current_state = STATE_SYNC; } else if (strcmp(cmd.root, "go") == 0) { current_state = STATE_ACTIVE; } else { printf("Invalid command: %s\n", cmd.root); } } void handle_sync(uci_state *state, ucicmd cmd) { // when i come up with some info to give: // printf("info\n"); printf("readyok\n"); current_state = STATE_IDLE; } void handle_ping(uci_state *state, ucicmd cmd) { // when i come up with some info to give: // printf("info\n"); // // if (TODO) { // printf("bestmove\n"); // current_state = STATE_IDLE; // } printf("readyok\n"); current_state = STATE_ACTIVE; } void handle_active(uci_state *state, ucicmd cmd) { if (cmd.empty) { return; } // TODO: this section will call the engine to analysis if (strcmp(cmd.root, "isready") == 0) { current_state = STATE_PING; } else if (strcmp(cmd.root, "stop") == 0) { current_state = STATE_HALT; } else { printf("Invalid command: %s\n", cmd.root); } } void handle_halt(uci_state *state, ucicmd cmd) { // when i come up with some info to give: // printf("info\n"); printf("bestmove 0000\n"); // TODO: idk get it rn current_state = STATE_IDLE; }