From 51d27e1ab9058c9e0fafb399e22edf7b38470510 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 27 Jul 2026 20:14:54 +0200 Subject: adding uci --- src/uci.cpp | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/uci.cpp (limited to 'src/uci.cpp') diff --git a/src/uci.cpp b/src/uci.cpp new file mode 100644 index 0000000..debf886 --- /dev/null +++ b/src/uci.cpp @@ -0,0 +1,213 @@ +#include "uci.hpp" +#include "board.hpp" +#include "bot.hpp" +#include "fen.hpp" +#include "moves.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +bool isValidChessRank(char rank) { + if (rank >= '1' && rank <= '8') { + return true; + } else { + return false; + } +} +bool isValidChessFile(char rank) { + if (rank >= 'A' && rank <= 'H') { + return true; + } else { + return false; + } +} +static Game initBoard(string startingFEN) { + Game b; + b.enPassant = IndexToPosition(0); // default value + b.canEnpassant = false; + b.state = TURN; + b.turn = true; + b.castle = ""; + b.halfMoveClock = 0; + b.MoveClock = 0; + setBoardFen(startingFEN, &b); + return b; +}; +void UciInit() { + Game game = + initBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); + + string line; + + while (getline(cin, line)) { + string cmd = line; + + transform(cmd.begin(), cmd.end(), cmd.begin(), ::toupper); + + if (cmd == "QUIT") { + break; + } + if (cmd == "UCI") { + cout << "uciok\n"; + cout.flush(); + } else if (cmd == "ISREADY") { + cout << "readyok\n"; + cout.flush(); + } else if (cmd.starts_with("GO")) { + Move best = EngineGetBestMove(&game); + + cout << "bestmove "; + cout << (char)(best.From.file + 'a') + << 8 - best.From.rank + << (char)(best.To.file + 'a') << 8 - best.To.rank; + println(); + + cout.flush(); + } + } +} +int startREPL() { + + Game g = + initBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); + Game *b = &g; + printBoard(b); + while (true) { + GetLegalMoves(b); + if (b->state == STALEMATE) { + printBoard(b); + std::println(); + std::cout << "\033[1mStalemate\033[0m" << "\n"; + std::println(); + return 0; + } + if (b->state == DRAW) { + printBoard(b); + std::println(); + std::cout << "\033[1mDraw\033[0m" << "\n"; + std::println(); + return 0; + } + if (b->state == WHITE_WON) { + printBoard(b); + std::cout << "\033[1mChechmate White won\033[0m" << "\n"; + return 0; + } + if (b->state == BLACK_WON) { + printBoard(b); + std::cout << "\033[1mCheckmate Black won\033[0m" << "\n"; + return 0; + } + if (b->state == TURN) { + if (true) { + Move move = EngineGetBestMove(b); + PlayMove(move, b); + printBoard(b); + continue; + } + } + std::cout << "> "; + std::string command; + if (!(std::cin >> command)) { + std::println(); + std::cout << "Exiting...\n"; + return EXIT_SUCCESS; + } + + std::transform(command.begin(), command.end(), command.begin(), ::toupper); + + std::cout << command << "\n"; + if (command == "EXIT") { + std::println(); + std::cout << "Exiting...\n"; + return EXIT_SUCCESS; + } + if (command == "RESING") { + std::cout << "\033[1mOK\033[0m" << "\n"; + if (b->turn) { + b->state = BLACK_WON; + } else { + b->state = WHITE_WON; + } + continue; + } + if (command == "BOARD") { + printBoard(b); + continue; + } + if (command == "MOVES" || command == "MOVE") { + auto moves = GetLegalMoves(b); + PrintMoves(moves); + continue; + } + if (command.length() != 4) { + std::cout << "Unknown Command, use EXIT to exit"; + std::println(); + continue; + } + if (b->state == TURN) { + if (!isValidChessFile(command[0])) { + std::cout << "ERROR: Expected valid file at first place"; + std::println(); + continue; + } + + if (!isValidChessRank(command[1])) { + std::cout << "ERROR: Expected valid rank at second place"; + std::println(); + continue; + } + + if (!isValidChessFile(command[2])) { + std::cout << "ERROR: Expected valid file at third place"; + std::println(); + continue; + } + + if (!isValidChessRank(command[3])) { + std::cout << "ERROR: Expected valid rank at four place"; + std::println(); + continue; + } + + // we know its a valid chess pos + int fromFile = command[0] - 'A'; + int fromRank = '8' - command[1]; + int toFile = command[2] - 'A'; + int toRank = '8' - command[3]; + std::cout << fromFile << "\n"; + std::cout << fromRank << "\n"; + std::cout << toFile << "\n"; + std::cout << toRank << "\n"; + Move move = { + {static_cast(fromRank), static_cast(fromFile)}, + {static_cast(toRank), static_cast(toFile)}}; + + auto moves = GetLegalMoves(b); + if (!(std::ranges::find(moves, move) != moves.end())) { + std::cout << "Invalid move!"; + std::println(); + PrintMoves(moves); + continue; + } + std::println(); + PlayMove(move, b); + printBoard(b); + } + } +} + +void PrintMoves(const std::vector &moves) { + std::cout << "Moves (" << moves.size() << "):\n"; + + for (const Move &move : moves) { + std::cout << (char)((int)move.From.file + 'A') << 8 - (int)move.From.rank + << " -> " << (char)((int)move.To.file + 'A') + << 8 - (int)move.To.rank << "\n"; + } +} -- cgit v1.2.3