129 lines
3.1 KiB
C++
129 lines
3.1 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 = divide(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
|