ArduChess/Uci.h

129 lines
3.2 KiB
C++

#ifndef __UCI_H_INC
#define __UCI_H_INC
#include "Tasks.h"
#define PS2(s) ([]{ static const char c[] PROGMEM = (s); return &c[0]; }())
namespace Uci {
typedef void uci_return;
typedef uci_return (*uci_handler)();
struct uci_cmd {
const char* command;
uci_handler handler;
};
void clear_line() {
int peek = Serial.peek();
if(peek == -1) return;
do {
peek = Serial.read();
} while(peek != '\n');
}
uci_return uci_hello() {
Serial.println(F("id name ArduChess\nid author Quinten Kock\nuciok"));
}
uci_return uci_unimpl() {
Serial.println(F("Function not implemented yet"));
}
uci_return uci_unknown() {
Serial.println(F("Not an UCI command"));
}
uci_return uci_perft() {
int depth = Serial.parseInt();
unsigned long startTime = millis();
unsigned long result = pseudo_perft(depth);
unsigned long elapsed = millis() - startTime;
Serial.print(F("perft("));
Serial.print(depth);
Serial.print(F(") result: "));
Serial.println(result);
Serial.print(F("Completed in "));
Serial.print(elapsed);
Serial.println(F("ms"));
}
const char UCI_COMMAND_uci[] PROGMEM = "uci";
const char UCI_COMMAND_debug[] PROGMEM = "debug";
const char UCI_COMMAND_isready[] PROGMEM = "isready";
const char UCI_COMMAND_setoption[] PROGMEM = "setoption";
const char UCI_COMMAND_ucinewgame[] PROGMEM = "ucinewgame";
const char UCI_COMMAND_position[] PROGMEM = "position";
const char UCI_COMMAND_go[] PROGMEM = "go";
const char UCI_COMMAND_stop[] PROGMEM = "stop";
const char UCI_COMMAND_ponderhit[] PROGMEM = "ponderhit";
const char UCI_COMMAND_quit[] PROGMEM = "quit";
const char UCI_COMMAND_bench[] PROGMEM = "bench";
const char UCI_COMMAND_perft[] PROGMEM = "perft";
const uci_cmd UCI_COMMANDS[] PROGMEM = {
{UCI_COMMAND_uci, &uci_hello},
{UCI_COMMAND_debug, &uci_unimpl},
{UCI_COMMAND_isready, &uci_unimpl},
{UCI_COMMAND_setoption, &uci_unimpl},
{UCI_COMMAND_ucinewgame, &uci_unimpl},
{UCI_COMMAND_position, &uci_unimpl},
{UCI_COMMAND_go, &uci_unimpl},
{UCI_COMMAND_stop, &uci_unimpl},
{UCI_COMMAND_ponderhit, &uci_unimpl},
{UCI_COMMAND_quit, &uci_unimpl},
{UCI_COMMAND_bench, &bench},
{UCI_COMMAND_perft, &uci_perft},
};
const uci_cmd UCI_INVALID = {PS2(""), &uci_unknown};
uci_cmd get_uci_command(const char* command) {
size_t command_num = sizeof(UCI_COMMANDS) / sizeof(uci_cmd);
for(size_t i = 0; i < command_num; i++) {
size_t ci = 0;
uci_cmd to_try;
memcpy_P(&to_try, &UCI_COMMANDS[i], sizeof(uci_cmd));
while(true) {
char reference = pgm_read_byte_near(to_try.command + ci);
if(reference != command[ci]) {
break;
}
if(command[ci] == '\0') {
return to_try;
}
ci++;
}
}
return UCI_INVALID;
}
String read_word() {
int incoming = Serial.read();
String str = String();
do {
if(incoming != -1) {
str += (char)incoming;
}
incoming = Serial.read();
} while(incoming != '\n' && incoming != ' ');
return str;
}
uci_return handle_uci() {
if(Serial.available()) {
// There is input available; so likely a command
String command = read_word();
uci_cmd handler = get_uci_command(command.c_str());
handler.handler();
clear_line();
}
}
}
#endif