195 lines
5.1 KiB
C
195 lines
5.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <error.h>
|
|
#include <stdbool.h>
|
|
#include <ctype.h>
|
|
|
|
#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<NUM_CMDS; active_command++){
|
|
if(strncmp(CMDS[active_command], parse_pos, strlen(CMDS[active_command])) == 0){
|
|
break;
|
|
}
|
|
}
|
|
parse_pos+=(strlen(CMDS[active_command])+1);
|
|
switch(active_command){
|
|
case UCI:
|
|
_uci(parse_pos);
|
|
break;
|
|
case DEBUG:
|
|
_debug(parse_pos);
|
|
break;
|
|
case ISREADY:
|
|
_isready(parse_pos);
|
|
break;
|
|
case SETOPTION:
|
|
_setoption(parse_pos);
|
|
break;
|
|
case REGISTER:
|
|
_register(parse_pos);
|
|
break;
|
|
case UCINEWGAME:
|
|
_ucinewgame(parse_pos);
|
|
break;
|
|
case POSITION:
|
|
_position(parse_pos);
|
|
break;
|
|
case GO:
|
|
_go(parse_pos);
|
|
break;
|
|
case STOP:
|
|
_stop(parse_pos);
|
|
break;
|
|
case PONDERHIT:
|
|
_ponderhit(parse_pos);
|
|
break;
|
|
case QUIT:
|
|
_quit(parse_pos);
|
|
break;
|
|
}
|
|
}
|
|
|