#ifndef __UCI_H_INC #define __UCI_H_INC #include "Tasks.h" #define PS2(s) ([]{ static const char c[] PROGMEM = (s); return &c[0]; }()) 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 result = pseudo_perft(depth); Serial.print(F("perft(")); Serial.print(depth); Serial.print(F(") result: ")); Serial.println(result); } 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