#include "uci.hpp" #include "board/board.hpp" #include "board/fen.hpp" #include "bot.hpp" #include "misc.hpp" #include "moves.hpp" #include "zobrist/zobrist.hpp" #include #include #include #include #include #include #include #include #include #include #include #include std::ofstream uciLog("cache/uci_log.txt", std::ios::app); void LogUci(const std::string &message) { if (!uciLog.is_open()) { return; } auto now = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::to_time_t(now); uciLog << "[" << std::put_time(std::localtime(&time), "%H:%M:%S") << "] " << message << "\n"; uciLog.flush(); } using namespace std; Move UciToMove(string uci) { Position from; Position to; from.file = uci[0] - 'a'; from.rank = '8' - uci[1]; to.file = uci[2] - 'a'; to.rank = '8' - uci[3]; return {from, to}; } Game initBoard( string startingFEN, std::unordered_map *transPositions) { Game b{}; b.enPassant = IndexToPosition(0); // default value b.canEnpassant = false; b.state = TURN; b.turn = true; b.halfMoveClock = 0; b.MoveClock = 0; b.Transpositions = transPositions; Piece EmptyPiece = { false, NONEPIECE, }; for (int i = 0; i < 64; i++) { b.pieces[i] = EmptyPiece; }; setBoardFen(startingFEN, &b); uint64_t key = GenerateZobristKey(&b); b.ThreeFoldMap[key] = 1; return b; }; void Uci() { unordered_map transpositions = {}; Game game = initBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", &transpositions); string line; while (getline(cin, line)) { string cmd = line; LogUci("GUI -> ENGINE: " + line); transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower); if (cmd == "quit") { break; } if (cmd == "board") { for (int rank = 0; rank < 8; rank++) { std::printf("%d |", 8 - rank); for (int file = 0; file < 8; file++) { Piece piece = game.pieces[rank * 8 + file]; std::printf(" %d%d", piece.type, piece.color); } std::printf(" | %d\n", 8 - rank); } } if (cmd == "uci") { cout << "id name " << engine_version() << "\n"; cout << "uciok\n"; cout.flush(); } else if (cmd == "ucinewgame") { game = initBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", &transpositions); } else if (cmd == "isready") { cout << "readyok\n"; cout.flush(); } else if (cmd.starts_with("go")) { stringstream ss(line); string token; int depth = -1; ss >> token; // go while (ss >> token) { if (token == "depth") { ss >> depth; break; } } Move best = GetBestMove(&game, depth); cout << "bestmove "; cout << (char)(best.From.file + 'a') << 8 - best.From.rank << (char)(best.To.file + 'a') << 8 - best.To.rank; if (best.promotion != NONEPIECE) { switch (best.promotion) { case QUEEN: cout << "q"; break; case ROOK: cout << "r"; break; case KNIGHT: cout << "n"; break; case BISHOP: cout << "b"; break; default: assert(false && "Unexpected promotion type"); } } cout << "\n"; cout.flush(); } else if (cmd.starts_with("position")) { stringstream ss(line); string token; ss >> token; // position ss >> token; if (token == "startpos") { game = initBoard( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", &transpositions); } else if (token == "fen") { string fen; string part; // FEN has spaces, need 6 parts for (int i = 0; i < 6; i++) { ss >> part; if (i) fen += " "; fen += part; } game = initBoard(fen, &transpositions); } // check for moves while (ss >> token) { if (token == "moves") break; } while (ss >> token) { Move move = UciToMove(token); MakeMove(move, &game); } } else if (cmd.starts_with("perft")) { std::istringstream iss(cmd); std::string word; int depth = -1; if (!(iss >> word >> depth) || word != "perft" || depth < 0) { cout << "info string usage: perft \n"; cout.flush(); continue; } int count = MoveGenTest(depth, &game); cout << count << "\n"; cout.flush(); } } }