Support CECP highlight command
authorFabian Fichter <ianfab@users.noreply.github.com>
Wed, 6 May 2020 18:55:22 +0000 (20:55 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Wed, 6 May 2020 18:55:22 +0000 (20:55 +0200)
Significantly improves Winboard/XBoard compatibility.

Closes #121.

src/xboard.cpp

index 243bd51..f37f349 100644 (file)
@@ -108,12 +108,61 @@ void StateMachine::process_command(Position& pos, std::string token, std::istrin
       for (std::string v : variants.get_keys())
           if (v != "chess")
               vars += "," + v;
-      sync_cout << "feature setboard=1 usermove=1 time=1 memory=1 smp=1 colors=0 draw=0 name=0 sigint=0 ping=1 myname=Fairy-Stockfish variants=\""
+      sync_cout << "feature setboard=1 usermove=1 time=1 memory=1 smp=1 colors=0 draw=0 "
+                << "highlight=1 name=0 sigint=0 ping=1 myname=Fairy-Stockfish variants=\""
                 << vars << "\""
                 << Options << sync_endl;
       sync_cout << "feature done=1" << sync_endl;
   }
   else if (token == "accepted" || token == "rejected" || token == "result" || token == "?") {}
+  else if (token == "hover" || token == "put") {}
+  else if (token == "lift")
+  {
+      if (is >> token)
+      {
+          Bitboard promotions = 0, captures = 0, quiets = 0;
+          // Collect targets
+          for (const auto& m : MoveList<LEGAL>(pos))
+          {
+              Square from = from_sq(m), to = to_sq(m);
+              if (is_ok(from) && UCI::square(pos, from) == token)
+              {
+                  if (type_of(m) == PROMOTION)
+                      promotions |= to;
+                  else if (pos.capture(m))
+                      captures |= to;
+                  else
+                  {
+                      if (type_of(m) == CASTLING && !pos.is_chess960())
+                          to = make_square(to > from ? pos.castling_kingside_file()
+                                                     : pos.castling_queenside_file(), rank_of(from));
+                      quiets |= to;
+                  }
+              }
+          }
+          // Generate color FEN
+          int emptyCnt;
+          std::ostringstream ss;
+          for (Rank r = pos.max_rank(); r >= RANK_1; --r)
+          {
+              for (File f = FILE_A; f <= pos.max_file(); ++f)
+              {
+                  for (emptyCnt = 0; f <= pos.max_file() && !((promotions | captures | quiets) & make_square(f, r)); ++f)
+                      ++emptyCnt;
+
+                  if (emptyCnt)
+                      ss << emptyCnt;
+
+                  if (f <= pos.max_file())
+                      ss << (promotions & make_square(f, r) ? "M" : captures & make_square(f, r) ? "R" : "Y");
+              }
+
+              if (r > RANK_1)
+                  ss << '/';
+          }
+          sync_cout << "highlight " << ss.str() << sync_endl;
+      }
+  }
   else if (token == "ping")
   {
       if (!(is >> token))