X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fuci.cpp;h=cfd112172bf11fe048c4a78447c43888006ca10b;hp=e4a4393cfe7280d4e3ef9bbfd77da6e86d9cba30;hb=5ab55827b84f1aef79478ec9b030330973036bda;hpb=b2c0634d4898a78a9e82fca9197467d442e5cb95 diff --git a/src/uci.cpp b/src/uci.cpp index e4a4393c..cfd11217 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -23,12 +23,12 @@ #include #include "evaluate.h" -#include "notation.h" +#include "movegen.h" #include "position.h" #include "search.h" #include "thread.h" #include "tt.h" -#include "ucioption.h" +#include "uci.h" using namespace std; @@ -72,7 +72,7 @@ namespace { SetupStates = Search::StateStackPtr(new std::stack()); // Parse move list (if any) - while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE) + while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) { SetupStates->push(StateInfo()); pos.do_move(m, SetupStates->top()); @@ -117,7 +117,7 @@ namespace { { if (token == "searchmoves") while (is >> token) - limits.searchmoves.push_back(move_from_uci(pos, token)); + limits.searchmoves.push_back(UCI::to_move(pos, token)); else if (token == "wtime") is >> limits.time[WHITE]; else if (token == "btime") is >> limits.time[BLACK]; @@ -174,12 +174,14 @@ void UCI::loop(int argc, char* argv[]) { else Search::Limits.ponder = false; } - else if (token == "perft" && (is >> token)) // Read perft depth + else if (token == "perft") { + int depth; stringstream ss; + is >> depth; ss << Options["Hash"] << " " - << Options["Threads"] << " " << token << " current perft"; + << Options["Threads"] << " " << depth << " current " << token; benchmark(pos, ss); } @@ -188,18 +190,13 @@ void UCI::loop(int argc, char* argv[]) { << "position key: " << setw(16) << pos.key() << "\nmaterial key: " << setw(16) << pos.material_key() << "\npawn key: " << setw(16) << pos.pawn_key() - << dec << sync_endl; + << dec << nouppercase << setfill(' ') << sync_endl; else if (token == "uci") sync_cout << "id name " << engine_info(true) << "\n" << Options << "\nuciok" << sync_endl; - else if (token == "eval") - { - Search::RootColor = pos.side_to_move(); // Ensure it is set - sync_cout << Eval::trace(pos) << sync_endl; - } else if (token == "ucinewgame") TT.clear(); else if (token == "go") go(pos, is); else if (token == "position") position(pos, is); @@ -208,6 +205,7 @@ void UCI::loop(int argc, char* argv[]) { else if (token == "bench") benchmark(pos, is); else if (token == "d") sync_cout << pos.pretty() << sync_endl; else if (token == "isready") sync_cout << "readyok" << sync_endl; + else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl; else sync_cout << "Unknown command: " << cmd << sync_endl; @@ -215,3 +213,79 @@ void UCI::loop(int argc, char* argv[]) { Threads.wait_for_think_finished(); // Cannot quit whilst the search is running } + + +/// format_value() converts a Value to a string suitable for use with the UCI +/// protocol specifications: +/// +/// cp The score from the engine's point of view in centipawns. +/// mate Mate in y moves, not plies. If the engine is getting mated +/// use negative values for y. + +string UCI::format_value(Value v, Value alpha, Value beta) { + + stringstream ss; + + if (abs(v) < VALUE_MATE_IN_MAX_PLY) + ss << "cp " << v * 100 / PawnValueEg; + else + ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; + + ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : ""); + + return ss.str(); +} + + +/// format_square() converts a Square to a string (g1, a7, etc.) + +std::string UCI::format_square(Square s) { + + char ch[] = { char('a' + file_of(s)), + char('1' + rank_of(s)), 0 }; // Zero-terminating + return ch; +} + + +/// format_move() converts a Move to a string in coordinate notation +/// (g1f3, a7a8q, etc.). The only special case is castling moves, where we print +/// in the e1g1 notation in normal chess mode, and in e1h1 notation in chess960 +/// mode. Internally castling moves are always encoded as "king captures rook". + +string UCI::format_move(Move m, bool chess960) { + + Square from = from_sq(m); + Square to = to_sq(m); + + if (m == MOVE_NONE) + return "(none)"; + + if (m == MOVE_NULL) + return "0000"; + + if (type_of(m) == CASTLING && !chess960) + to = make_square(to > from ? FILE_G : FILE_C, rank_of(from)); + + string move = format_square(from) + format_square(to); + + if (type_of(m) == PROMOTION) + move += " pnbrqk"[promotion_type(m)]; + + return move; +} + + +/// to_move() takes a position and a string representing a move in +/// simple coordinate notation and returns an equivalent legal Move if any. + +Move UCI::to_move(const Position& pos, string& str) { + + if (str.length() == 5) // Junior could send promotion piece in uppercase + str[4] = char(tolower(str[4])); + + for (MoveList it(pos); *it; ++it) + if (str == format_move(*it, pos.is_chess960())) + return *it; + + return MOVE_NONE; +}