+ token.clear(); // getline() could return empty or blank line
+ is >> skipws >> token;
+
+ // The GUI sends 'ponderhit' to tell us to ponder on the same move the
+ // opponent has played. In case Signals.stopOnPonderhit is set we are
+ // waiting for 'ponderhit' to stop the search (for instance because we
+ // already ran out of time), otherwise we should continue searching but
+ // switching from pondering to normal search.
+ if ( token == "quit"
+ || token == "stop"
+ || (token == "ponderhit" && Search::Signals.stopOnPonderhit))
+ {
+ Search::Signals.stop = true;
+ Threads.main()->start_searching(true); // Could be sleeping
+ }
+ else if (token == "ponderhit")
+ Search::Limits.ponder = 0; // Switch to normal search
+
+ else if (token == "uci")
+ sync_cout << "id name " << engine_info(true)
+ << "\n" << Options
+ << "\nuciok" << sync_endl;
+
+ else if (token == "ucinewgame")
+ {
+ Search::clear();
+ Tablebases::init(Options["SyzygyPath"]);
+ Time.availableNodes = 0;
+ }
+ else if (token == "isready") sync_cout << "readyok" << sync_endl;
+ else if (token == "go") go(pos, is);
+ else if (token == "position") position(pos, is);
+ else if (token == "setoption") setoption(is);
+
+ // Additional custom non-UCI commands, useful for debugging
+ else if (token == "flip") pos.flip();
+ else if (token == "bench") benchmark(pos, is);
+ else if (token == "d") sync_cout << pos << sync_endl;
+ else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
+ else if (token == "perft")
+ {
+ int depth;
+ stringstream ss;
+
+ is >> depth;
+ ss << Options["Hash"] << " "
+ << Options["Threads"] << " " << depth << " current perft";
+
+ benchmark(pos, ss);
+ }
+ else
+ sync_cout << "Unknown command: " << cmd << sync_endl;
+
+ } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
+
+ Threads.main()->wait_for_search_finished();
+}
+
+
+/// UCI::value() converts a Value to a string suitable for use with the UCI
+/// protocol specification:
+///
+/// cp <x> The score from the engine's point of view in centipawns.
+/// mate <y> Mate in y moves, not plies. If the engine is getting mated
+/// use negative values for y.
+
+string UCI::value(Value v) {
+
+ 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;
+
+ return ss.str();
+}
+
+
+/// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.)
+
+std::string UCI::square(Square s) {
+ return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
+}
+
+
+/// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
+/// The only special case is castling, where we print in the e1g1 notation in
+/// normal chess mode, and in e1h1 notation in chess960 mode. Internally all
+/// castling moves are always encoded as 'king captures rook'.
+
+string UCI::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 = UCI::square(from) + UCI::square(to);
+
+ if (type_of(m) == PROMOTION)
+ move += " pnbrqk"[promotion_type(m)];
+
+ return move;
+}
+
+
+/// UCI::to_move() converts a string representing a move in coordinate notation
+/// (g1f3, a7a8q) to the corresponding 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 (const auto& m : MoveList<LEGAL>(pos))
+ if (str == UCI::move(m, pos.is_chess960()))
+ return m;
+
+ return MOVE_NONE;