Convert protocol option to enum
authorFabian Fichter <ianfab@users.noreply.github.com>
Mon, 16 May 2022 19:46:50 +0000 (21:46 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Tue, 17 May 2022 11:34:00 +0000 (13:34 +0200)
Closes #477.

src/position.cpp
src/search.cpp
src/uci.cpp
src/uci.h
src/ucioption.cpp

index 7009ff6..14dc975 100644 (file)
@@ -396,7 +396,7 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
           st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
 #ifdef LARGEBOARDS
           // Consider different rank numbering in CECP
-          if (max_rank() == RANK_10 && Options["Protocol"] == "xboard")
+          if (max_rank() == RANK_10 && CurrentProtocol == XBOARD)
               st->epSquare += NORTH;
 #endif
 
index 9105577..b7947eb 100644 (file)
@@ -190,14 +190,14 @@ void MainThread::search() {
 
   Eval::NNUE::verify();
 
-  if (rootMoves.empty() || (Options["Protocol"] == "xboard" && rootPos.is_optional_game_end()))
+  if (rootMoves.empty() || (CurrentProtocol == XBOARD && rootPos.is_optional_game_end()))
   {
       rootMoves.emplace_back(MOVE_NONE);
       Value variantResult;
       Value result =  rootPos.is_game_end(variantResult) ? variantResult
                     : rootPos.checkers()                 ? rootPos.checkmate_value()
                                                          : rootPos.stalemate_value();
-      if (Options["Protocol"] == "xboard")
+      if (CurrentProtocol == XBOARD)
       {
           // rotate MOVE_NONE to front (for optional game end)
           std::rotate(rootMoves.rbegin(), rootMoves.rbegin() + 1, rootMoves.rend());
@@ -218,7 +218,7 @@ void MainThread::search() {
   }
 
   // Sit in bughouse variants if partner requested it or we are dead
-  if (rootPos.two_boards() && !Threads.abort && Options["Protocol"] == "xboard")
+  if (rootPos.two_boards() && !Threads.abort && CurrentProtocol == XBOARD)
   {
       while (!Threads.stop && (Partner.sitRequested || (Partner.weDead && !Partner.partnerDead)) && Time.elapsed() < Limits.time[us] - 1000)
       {}
@@ -259,7 +259,7 @@ void MainThread::search() {
   if (bestThread != this)
       sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl;
 
-  if (Options["Protocol"] == "xboard")
+  if (CurrentProtocol == XBOARD)
   {
       Move bestMove = bestThread->rootMoves[0].pv[0];
       // Wait for virtual drop to become real
@@ -539,7 +539,7 @@ void Thread::search() {
               totalTime = std::min(500.0, totalTime);
 
           // Update partner in bughouse variants
-          if (completedDepth >= 8 && rootPos.two_boards() && Options["Protocol"] == "xboard")
+          if (completedDepth >= 8 && rootPos.two_boards() && CurrentProtocol == XBOARD)
           {
               // Communicate clock times relevant for sitting decisions
               if (Limits.time[us])
@@ -1112,7 +1112,7 @@ moves_loop: // When in check, search starts from here
 
       ss->moveCount = ++moveCount;
 
-      if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000 && Options["Protocol"] != "xboard")
+      if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000 && is_uci_dialect(CurrentProtocol))
           sync_cout << "info depth " << depth
                     << " currmove " << UCI::move(pos, move)
                     << " currmovenumber " << moveCount + thisThread->pvIdx << sync_endl;
@@ -1989,7 +1989,7 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
       if (ss.rdbuf()->in_avail()) // Not at first line
           ss << "\n";
 
-      if (Options["Protocol"] == "xboard")
+      if (CurrentProtocol == XBOARD)
       {
           ss << d << " "
              << UCI::value(v) << " "
index 9a87ab7..34b7e0c 100644 (file)
@@ -102,7 +102,7 @@ namespace {
 
     is >> token; // Consume "name" token
 
-    if (Options["Protocol"] == "ucci")
+    if (CurrentProtocol == UCCI)
         name = token;
     else
     // Read option name (can contain spaces)
@@ -136,7 +136,7 @@ namespace {
     limits.startTime = now(); // As early as possible!
 
     limits.banmoves = banmoves;
-    bool isUsi = Options["Protocol"] == "usi";
+    bool isUsi = CurrentProtocol == USI;
     int secResolution = Options["usemillisec"] ? 1 : 1000;
 
     while (is >> token)
@@ -345,26 +345,29 @@ void UCI::loop(int argc, char* argv[]) {
 
       else if (token == "uci" || token == "usi" || token == "ucci" || token == "xboard")
       {
-          Options["Protocol"].set_default(token);
+          CurrentProtocol =  token == "uci"  ? UCI_GENERAL
+                           : token == "usi"  ? USI
+                           : token == "ucci" ? UCCI
+                           : XBOARD;
           string defaultVariant = string(
 #ifdef LARGEBOARDS
-                                           token == "usi"  ? "shogi"
-                                         : token == "ucci" ? "xiangqi"
+                                           CurrentProtocol == USI  ? "shogi"
+                                         : CurrentProtocol == UCCI ? "xiangqi"
 #else
-                                           token == "usi"  ? "minishogi"
-                                         : token == "ucci" ? "minixiangqi"
+                                           CurrentProtocol == USI  ? "minishogi"
+                                         : CurrentProtocol == UCCI ? "minixiangqi"
 #endif
                                                            : "chess");
           Options["UCI_Variant"].set_default(defaultVariant);
           std::istringstream ss("startpos");
           position(pos, ss, states);
-          if (token == "uci" || token == "usi" || token == "ucci")
+          if (is_uci_dialect(CurrentProtocol))
               sync_cout << "id name " << engine_info(true)
                           << "\n" << Options
                           << "\n" << token << "ok"  << sync_endl;
       }
 
-      else if (Options["Protocol"] == "xboard")
+      else if (CurrentProtocol == XBOARD)
           XBoard::stateMachine->process_command(token, is);
 
       else if (token == "setoption")  setoption(is);
@@ -398,9 +401,9 @@ void UCI::loop(int argc, char* argv[]) {
       else if (token == "fen" || token == "startpos")
       {
 #ifdef LARGEBOARDS
-          if (Options["Protocol"] == "uci" && Options["UCI_Variant"] == "chess")
+          if (CurrentProtocol == UCI_GENERAL && Options["UCI_Variant"] == "chess")
           {
-              Options["Protocol"].set_default("ucicyclone");
+              CurrentProtocol = UCI_CYCLONE;
               Options["UCI_Variant"].set_default("xiangqi");
           }
 #endif
@@ -427,7 +430,7 @@ string UCI::value(Value v) {
 
   stringstream ss;
 
-  if (Options["Protocol"] == "xboard")
+  if (CurrentProtocol == XBOARD)
   {
       if (abs(v) < VALUE_MATE_IN_MAX_PLY)
           ss << v * 100 / PawnValueEg;
@@ -436,8 +439,8 @@ string UCI::value(Value v) {
   } else
 
   if (abs(v) < VALUE_MATE_IN_MAX_PLY)
-      ss << (Options["Protocol"] == "ucci" ? "" : "cp ") << v * 100 / PawnValueEg;
-  else if (Options["Protocol"] == "usi")
+      ss << (CurrentProtocol == UCCI ? "" : "cp ") << v * 100 / PawnValueEg;
+  else if (CurrentProtocol == USI)
       // In USI, mate distance is given in ply
       ss << "mate " << (v > 0 ? VALUE_MATE - v : -VALUE_MATE - v);
   else
@@ -467,20 +470,20 @@ string UCI::wdl(Value v, int ply) {
 
 std::string UCI::square(const Position& pos, Square s) {
 #ifdef LARGEBOARDS
-  if (Options["Protocol"] == "usi")
+  if (CurrentProtocol == USI)
       return rank_of(s) < RANK_10 ? std::string{ char('1' + pos.max_file() - file_of(s)), char('a' + pos.max_rank() - rank_of(s)) }
                                   : std::string{ char('0' + (pos.max_file() - file_of(s) + 1) / 10),
                                                  char('0' + (pos.max_file() - file_of(s) + 1) % 10),
                                                  char('a' + pos.max_rank() - rank_of(s)) };
-  else if (pos.max_rank() == RANK_10 && Options["Protocol"] != "uci")
+  else if (pos.max_rank() == RANK_10 && CurrentProtocol != UCI_GENERAL)
       return std::string{ char('a' + file_of(s)), char('0' + rank_of(s)) };
   else
       return rank_of(s) < RANK_10 ? std::string{ char('a' + file_of(s)), char('1' + (rank_of(s) % 10)) }
                                   : std::string{ char('a' + file_of(s)), char('0' + ((rank_of(s) + 1) / 10)),
                                                  char('0' + ((rank_of(s) + 1) % 10)) };
 #else
-  return Options["Protocol"] == "usi" ? std::string{ char('1' + pos.max_file() - file_of(s)), char('a' + pos.max_rank() - rank_of(s)) }
-                                      : std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
+  return CurrentProtocol == USI ? std::string{ char('1' + pos.max_file() - file_of(s)), char('a' + pos.max_rank() - rank_of(s)) }
+                                : std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
 #endif
 }
 
@@ -507,12 +510,12 @@ string UCI::move(const Position& pos, Move m) {
   Square to = to_sq(m);
 
   if (m == MOVE_NONE)
-      return Options["Protocol"] == "usi" ? "resign" : "(none)";
+      return CurrentProtocol == USI ? "resign" : "(none)";
 
   if (m == MOVE_NULL)
       return "0000";
 
-  if (is_pass(m) && Options["Protocol"] == "xboard")
+  if (is_pass(m) && CurrentProtocol == XBOARD)
       return "@@@@";
 
   if (is_gating(m) && gating_square(m) == to)
@@ -525,7 +528,7 @@ string UCI::move(const Position& pos, Move m) {
           to = to_sq(m);
   }
 
-  string move = (type_of(m) == DROP ? UCI::dropped_piece(pos, m) + (Options["Protocol"] == "usi" ? '*' : '@')
+  string move = (type_of(m) == DROP ? UCI::dropped_piece(pos, m) + (CurrentProtocol == USI ? '*' : '@')
                                     : UCI::square(pos, from)) + UCI::square(pos, to);
 
   if (type_of(m) == PROMOTION)
@@ -567,26 +570,25 @@ Move UCI::to_move(const Position& pos, string& str) {
   return MOVE_NONE;
 }
 
-std::string UCI::option_name(std::string name, std::string protocol) {
-  if (protocol == "ucci" && name == "Hash")
+std::string UCI::option_name(std::string name) {
+  if (CurrentProtocol == UCCI && name == "Hash")
       return "hashsize";
-  if (protocol == "usi")
+  if (CurrentProtocol == USI)
   {
       if (name == "Hash" || name == "Ponder" || name == "MultiPV")
           return "USI_" + name;
       if (name.substr(0, 4) == "UCI_")
           name = "USI_" + name.substr(4);
   }
-  if (protocol == "ucci" || protocol == "usi")
+  if (CurrentProtocol == UCCI || CurrentProtocol == USI)
       std::replace(name.begin(), name.end(), ' ', '_');
   return name;
 }
 
 bool UCI::is_valid_option(UCI::OptionsMap& options, std::string& name) {
-  std::string protocol = options["Protocol"];
   for (const auto& it : options)
   {
-      std::string optionName = option_name(it.first, protocol);
+      std::string optionName = option_name(it.first);
       if (!options.key_comp()(optionName, name) && !options.key_comp()(name, optionName))
       {
           name = it.first;
@@ -596,4 +598,6 @@ bool UCI::is_valid_option(UCI::OptionsMap& options, std::string& name) {
   return false;
 }
 
+Protocol CurrentProtocol = UCI_GENERAL; // Global object
+
 } // namespace Stockfish
index 6c12216..ef22a53 100644 (file)
--- a/src/uci.h
+++ b/src/uci.h
@@ -93,13 +93,27 @@ std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
 std::string wdl(Value v, int ply);
 Move to_move(const Position& pos, std::string& str);
 
-std::string option_name(std::string name, std::string protocol);
+std::string option_name(std::string name);
 bool is_valid_option(UCI::OptionsMap& options, std::string& name);
 
 } // namespace UCI
 
 extern UCI::OptionsMap Options;
 
+enum Protocol {
+  UCI_GENERAL,
+  USI,
+  UCCI,
+  UCI_CYCLONE,
+  XBOARD,
+};
+
+constexpr bool is_uci_dialect(Protocol p) {
+  return p != XBOARD;
+}
+
+extern Protocol CurrentProtocol;
+
 } // namespace Stockfish
 
 #endif // #ifndef UCI_H_INCLUDED
index d87e232..782d51d 100644 (file)
@@ -92,7 +92,7 @@ void on_variant_change(const Option &o) {
     if (standard_variants.find(o) != standard_variants.end())
         return;
     int pocketsize = v->pieceDrops ? (v->pocketSize ? v->pocketSize : v->pieceTypes.size()) : 0;
-    if (Options["Protocol"] == "xboard")
+    if (CurrentProtocol == XBOARD)
     {
         // Overwrite setup command for Janggi variants
         auto itJanggi = variants.find("janggi");
@@ -178,7 +178,6 @@ void init(OptionsMap& o) {
 
   constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
 
-  o["Protocol"]              << Option("uci", {"uci", "usi", "ucci", "ucicyclone", "xboard"});
   o["Debug Log File"]        << Option("", on_logger);
   o["Threads"]               << Option(1, 1, 512, on_threads);
   o["Hash"]                  << Option(16, 1, MaxHashMB, on_hash_size);
@@ -216,12 +215,11 @@ void init(OptionsMap& o) {
 
 std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
 
-  if (Options["Protocol"] == "xboard")
+  if (CurrentProtocol == XBOARD)
   {
       for (size_t idx = 0; idx < om.size(); ++idx)
           for (const auto& it : om)
-              if (it.second.idx == idx && it.first != "Protocol" && it.first != "UCI_Variant"
-                                       && it.first != "Threads" && it.first != "Hash")
+              if (it.second.idx == idx && it.first != "UCI_Variant" && it.first != "Threads" && it.first != "Hash")
               {
                   const Option& o = it.second;
                   os << "\nfeature option=\"" << it.first << " -" << o.type;
@@ -254,11 +252,11 @@ std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
           {
               const Option& o = it.second;
               // UCI dialects do not allow spaces
-              if (Options["Protocol"] == "ucci" || Options["Protocol"] == "usi")
+              if (CurrentProtocol == UCCI || CurrentProtocol == USI)
               {
-                  string name = option_name(it.first, Options["Protocol"]);
+                  string name = option_name(it.first);
                   // UCCI skips "name"
-                  os << "\noption " << (Options["Protocol"] == "ucci" ? "" : "name ") << name << " type " << o.type;
+                  os << "\noption " << (CurrentProtocol == UCCI ? "" : "name ") << name << " type " << o.type;
               }
               else
                   os << "\noption name " << it.first << " type " << o.type;