Subversion Repositories Games.Chess Giants

Rev

Rev 96 | Rev 169 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
  3.   Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
  4.   Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
  5.   Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
  6.  
  7.   Stockfish is free software: you can redistribute it and/or modify
  8.   it under the terms of the GNU General Public License as published by
  9.   the Free Software Foundation, either version 3 of the License, or
  10.   (at your option) any later version.
  11.  
  12.   Stockfish is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License
  18.   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21. #include <iostream>
  22. #include <sstream>
  23. #include <string>
  24.  
  25. #include "evaluate.h"
  26. #include "movegen.h"
  27. #include "position.h"
  28. #include "search.h"
  29. #include "thread.h"
  30. #include "timeman.h"
  31. #include "uci.h"
  32.  
  33. using namespace std;
  34.  
  35. extern void benchmark(const Position& pos, istream& is);
  36.  
  37. namespace {
  38.  
  39.   // FEN string of the initial position, normal chess
  40.   const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  41.  
  42.   // A list to keep track of the position states along the setup moves (from the
  43.   // start position to the position just before the search starts). Needed by
  44.   // 'draw by repetition' detection.
  45.   StateListPtr States(new std::deque<StateInfo>(1));
  46.  
  47.  
  48.   // position() is called when engine receives the "position" UCI command.
  49.   // The function sets up the position described in the given FEN string ("fen")
  50.   // or the starting position ("startpos") and then makes the moves given in the
  51.   // following move list ("moves").
  52.  
  53.   void position(Position& pos, istringstream& is) {
  54.  
  55.     Move m;
  56.     string token, fen;
  57.  
  58.     is >> token;
  59.  
  60.     if (token == "startpos")
  61.     {
  62.         fen = StartFEN;
  63.         is >> token; // Consume "moves" token if any
  64.     }
  65.     else if (token == "fen")
  66.         while (is >> token && token != "moves")
  67.             fen += token + " ";
  68.     else
  69.         return;
  70.  
  71.     States = StateListPtr(new std::deque<StateInfo>(1));
  72.     pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main());
  73.  
  74.     // Parse move list (if any)
  75.     while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
  76.     {
  77.         States->push_back(StateInfo());
  78.         pos.do_move(m, States->back(), pos.gives_check(m));
  79.     }
  80.   }
  81.  
  82.  
  83.   // setoption() is called when engine receives the "setoption" UCI command. The
  84.   // function updates the UCI option ("name") to the given value ("value").
  85.  
  86.   void setoption(istringstream& is) {
  87.  
  88.     string token, name, value;
  89.  
  90.     is >> token; // Consume "name" token
  91.  
  92.     // Read option name (can contain spaces)
  93.     while (is >> token && token != "value")
  94.         name += string(" ", name.empty() ? 0 : 1) + token;
  95.  
  96.     // Read option value (can contain spaces)
  97.     while (is >> token)
  98.         value += string(" ", value.empty() ? 0 : 1) + token;
  99.  
  100.     if (Options.count(name))
  101.         Options[name] = value;
  102.     else
  103.         sync_cout << "No such option: " << name << sync_endl;
  104.   }
  105.  
  106.  
  107.   // go() is called when engine receives the "go" UCI command. The function sets
  108.   // the thinking time and other parameters from the input string, then starts
  109.   // the search.
  110.  
  111.   void go(Position& pos, istringstream& is) {
  112.  
  113.     Search::LimitsType limits;
  114.     string token;
  115.  
  116.     limits.startTime = now(); // As early as possible!
  117.  
  118.     while (is >> token)
  119.         if (token == "searchmoves")
  120.             while (is >> token)
  121.                 limits.searchmoves.push_back(UCI::to_move(pos, token));
  122.  
  123.         else if (token == "wtime")     is >> limits.time[WHITE];
  124.         else if (token == "btime")     is >> limits.time[BLACK];
  125.         else if (token == "winc")      is >> limits.inc[WHITE];
  126.         else if (token == "binc")      is >> limits.inc[BLACK];
  127.         else if (token == "movestogo") is >> limits.movestogo;
  128.         else if (token == "depth")     is >> limits.depth;
  129.         else if (token == "nodes")     is >> limits.nodes;
  130.         else if (token == "movetime")  is >> limits.movetime;
  131.         else if (token == "mate")      is >> limits.mate;
  132.         else if (token == "infinite")  limits.infinite = 1;
  133.         else if (token == "ponder")    limits.ponder = 1;
  134.  
  135.     Threads.start_thinking(pos, States, limits);
  136.   }
  137.  
  138. } // namespace
  139.  
  140.  
  141. /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate
  142. /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the
  143. /// GUI dies unexpectedly. When called with some command line arguments, e.g. to
  144. /// run 'bench', once the command is executed the function returns immediately.
  145. /// In addition to the UCI ones, also some additional debug commands are supported.
  146.  
  147. void UCI::loop(int argc, char* argv[]) {
  148.  
  149.   Position pos;
  150.   string token, cmd;
  151.  
  152.   pos.set(StartFEN, false, &States->back(), Threads.main());
  153.  
  154.   for (int i = 1; i < argc; ++i)
  155.       cmd += std::string(argv[i]) + " ";
  156.  
  157.   do {
  158.       if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF
  159.           cmd = "quit";
  160.  
  161.       istringstream is(cmd);
  162.  
  163.       token.clear(); // getline() could return empty or blank line
  164.       is >> skipws >> token;
  165.  
  166.       // The GUI sends 'ponderhit' to tell us to ponder on the same move the
  167.       // opponent has played. In case Signals.stopOnPonderhit is set we are
  168.       // waiting for 'ponderhit' to stop the search (for instance because we
  169.       // already ran out of time), otherwise we should continue searching but
  170.       // switching from pondering to normal search.
  171.       if (    token == "quit"
  172.           ||  token == "stop"
  173.           || (token == "ponderhit" && Search::Signals.stopOnPonderhit))
  174.       {
  175.           Search::Signals.stop = true;
  176.           Threads.main()->start_searching(true); // Could be sleeping
  177.       }
  178.       else if (token == "ponderhit")
  179.           Search::Limits.ponder = 0; // Switch to normal search
  180.  
  181.       else if (token == "uci")
  182.           sync_cout << "id name " << engine_info(true)
  183.                     << "\n"       << Options
  184.                     << "\nuciok"  << sync_endl;
  185.  
  186.       else if (token == "ucinewgame")
  187.       {
  188.           Search::clear();
  189.           Time.availableNodes = 0;
  190.       }
  191.       else if (token == "isready")    sync_cout << "readyok" << sync_endl;
  192.       else if (token == "go")         go(pos, is);
  193.       else if (token == "position")   position(pos, is);
  194.       else if (token == "setoption")  setoption(is);
  195.  
  196.       // Additional custom non-UCI commands, useful for debugging
  197.       else if (token == "flip")       pos.flip();
  198.       else if (token == "bench")      benchmark(pos, is);
  199.       else if (token == "d")          sync_cout << pos << sync_endl;
  200.       else if (token == "eval")       sync_cout << Eval::trace(pos) << sync_endl;
  201.       else if (token == "perft")
  202.       {
  203.           int depth;
  204.           stringstream ss;
  205.  
  206.           is >> depth;
  207.           ss << Options["Hash"]    << " "
  208.              << Options["Threads"] << " " << depth << " current perft";
  209.  
  210.           benchmark(pos, ss);
  211.       }
  212.       else
  213.           sync_cout << "Unknown command: " << cmd << sync_endl;
  214.  
  215.   } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
  216.  
  217.   Threads.main()->wait_for_search_finished();
  218. }
  219.  
  220.  
  221. /// UCI::value() converts a Value to a string suitable for use with the UCI
  222. /// protocol specification:
  223. ///
  224. /// cp <x>    The score from the engine's point of view in centipawns.
  225. /// mate <y>  Mate in y moves, not plies. If the engine is getting mated
  226. ///           use negative values for y.
  227.  
  228. string UCI::value(Value v) {
  229.  
  230.   stringstream ss;
  231.  
  232.   if (abs(v) < VALUE_MATE - MAX_PLY)
  233.       ss << "cp " << v * 100 / PawnValueEg;
  234.   else
  235.       ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
  236.  
  237.   return ss.str();
  238. }
  239.  
  240.  
  241. /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.)
  242.  
  243. std::string UCI::square(Square s) {
  244.   return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
  245. }
  246.  
  247.  
  248. /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
  249. /// The only special case is castling, where we print in the e1g1 notation in
  250. /// normal chess mode, and in e1h1 notation in chess960 mode. Internally all
  251. /// castling moves are always encoded as 'king captures rook'.
  252.  
  253. string UCI::move(Move m, bool chess960) {
  254.  
  255.   Square from = from_sq(m);
  256.   Square to = to_sq(m);
  257.  
  258.   if (m == MOVE_NONE)
  259.       return "(none)";
  260.  
  261.   if (m == MOVE_NULL)
  262.       return "0000";
  263.  
  264.   if (type_of(m) == CASTLING && !chess960)
  265.       to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
  266.  
  267.   string move = UCI::square(from) + UCI::square(to);
  268.  
  269.   if (type_of(m) == PROMOTION)
  270.       move += " pnbrqk"[promotion_type(m)];
  271.  
  272.   return move;
  273. }
  274.  
  275.  
  276. /// UCI::to_move() converts a string representing a move in coordinate notation
  277. /// (g1f3, a7a8q) to the corresponding legal Move, if any.
  278.  
  279. Move UCI::to_move(const Position& pos, string& str) {
  280.  
  281.   if (str.length() == 5) // Junior could send promotion piece in uppercase
  282.       str[4] = char(tolower(str[4]));
  283.  
  284.   for (const auto& m : MoveList<LEGAL>(pos))
  285.       if (str == UCI::move(m, pos.is_chess960()))
  286.           return m;
  287.  
  288.   return MOVE_NONE;
  289. }
  290.