#include #include #include #include #include #include #define MAX_LINE_WIDTH 256 enum CMD_CODES{ UCI = 0, DEBUG = 1, ISREADY = 2, SETOPTION = 3, REGISTER = 4, UCINEWGAME = 5, POSITION = 6, GO = 7, STOP = 8, PONDERHIT = 9, QUIT = 10 }; const char* CMDS[] = { "uci", "debug", "isready", "setoption name", "register", "ucinewgame", "position", "go", "stop", "ponderhit", "quit" }; #define NUM_CMDS (sizeof (CMDS) / sizeof (const char *)) typedef enum{ CHECK, SPIN, COMBO, BUTTON, STRING } option_type; typedef void button_handler(); typedef union { bool check; int spin; // maybe I could store an array of strings for combo, // and just have the first one be the one that gets modified, // the others being the possible variants char* combo; button_handler* button_handler; char* string; } option_data; typedef struct { char* name; option_type type; option_data data; } option; option options[] = { {"Ponder", CHECK, false}, {"OwnBook", CHECK, true} }; void _uci(char* parse_condition){ send_id(); send_opts(); send_uciok(); } void _debug(char* parse_condition){ if(strcmp("on", parse_condition)){ debug_mode = false; }else if(strcmp("off", parse_condition)){ debug_mode = true; }else{ printf("Warning: debug command without [ on | off ]"); } } void _isready(char* parse_condition){ while(true){ if(ready){ send_readyok(); break; } } } void _setoption(char* parse_condition){ int value_pos = find_value_pos(); //bit exessive, but oh well *shrugs* char option_str[value_pos]; strncpy(option_str, parse_condition, value_pos-1); char values_str[MAX_LINE_WIDTH]; strncpy(values_str, &parse_condition[value_pos+6], MAX_LINE_WIDTH); for(int i = 0; i < value_pos-1; i++){ option_str[i] = tolower(option_str[i]); } for(int i = 0; i < sizeof(options)/sizeof(option); i++){ if(strncmp(options[i].name, option_str, value_pos-1) == 0){ switch(options[i].type){ case CHECK: options[i].data = parse_check(values_str); case SPIN: options[i].data = parse_spin(values_str); case COMBO: // This is missing the info of what the possible strings are, to ensure that it's a valid string. // Integrating this into my rather neat data structure seems pain, so for now it won't get done options[i].data = parse_combo(values_str); case BUTTON: // Function pointer syntax is hard. This is meant to be a function call to the function pointer in data. // (this feels cursed as hell, but seemed like the only way to actually implement this x.x) *((button_handler*) options[i].data)(); case STRING: //this should really just be a quick verification of the termination options[i].data = parse_string(values_str); } } } } void _register(char* parse_condition){} void _ucinewgame(char* parse_condition){} void _position(char* parse_condition){} void _go(char* parse_condition){} void _stop(char* parse_condition){ run = false; } void _ponderhit(char* parse_condition){ ponder = true; } void _quit(char* parse_condition){ //letting the OS do the cleanup .-. //TODO: merge any threads together, and cleanly exit, rather than this mess x.x exit(1); } //reads a line of the input and parses it as UCI GUI->ENGINE communication void parse_line(){ char* parse_buff [MAX_LINE_WIDTH]; char* parse_pos = parse_buff; if(!fgets(parse_buff, MAX_LINE_WIDTH, stdin)){ perror("failed reading input"); exit(-1); } int active_command; for(active_command = 0; active_command