X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fuci.cpp;h=876bb1d90718bfc6870ea302ed2af02b6b93a704;hp=8d625bd9fe553510fce79ff0cf4e538131666e62;hb=94dd204c3b10ebe0e6c8df5d7c98de5ba4906cad;hpb=f5622cd5ec7836e899e263cc4cd4cc386e1ed5f4 diff --git a/src/uci.cpp b/src/uci.cpp index 8d625bd9..876bb1d9 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]; @@ -157,6 +157,7 @@ void UCI::loop(int argc, char* argv[]) { istringstream is(cmd); + token.clear(); // getline() could return empty or blank line is >> skipws >> token; if (token == "quit" || token == "stop" || token == "ponderhit") @@ -174,7 +175,7 @@ void UCI::loop(int argc, char* argv[]) { else Search::Limits.ponder = false; } - else if (token == "perft" || token == "divide") + else if (token == "perft") { int depth; stringstream ss; @@ -197,19 +198,15 @@ void UCI::loop(int argc, char* argv[]) { << "\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); else if (token == "setoption") setoption(is); else if (token == "flip") pos.flip(); else if (token == "bench") benchmark(pos, is); - else if (token == "d") sync_cout << pos.pretty() << sync_endl; + else if (token == "d") sync_cout << pos << 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; @@ -217,3 +214,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 - 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; +}