Subversion Repositories Games.Chess Giants

Rev

Rev 154 | 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.   // Stack 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.   Search::StateStackPtr SetupStates;
  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.     pos.set(fen, Options["UCI_Chess960"], Threads.main());
  72.     SetupStates = Search::StateStackPtr(new std::stack<StateInfo>);
  73.  
  74.     // Parse move list (if any)
  75.     while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
  76.     {
  77.         SetupStates->push(StateInfo());
  78.         pos.do_move(m, SetupStates->top(), pos.gives_check(m, CheckInfo(pos)));
  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(const 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, limits, SetupStates);
  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(StartFEN, false, Threads.main()); // The root position
  150.   string token, cmd;
  151.  
  152.   for (int i = 1; i < argc; ++i)
  153.       cmd += std::string(argv[i]) + " ";
  154.  
  155.   do {
  156.       if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF
  157.           cmd = "quit";
  158.  
  159.       istringstream is(cmd);
  160.  
  161.       token.clear(); // getline() could return empty or blank line
  162.       is >> skipws >> token;
  163.  
  164.       // The GUI sends 'ponderhit' to tell us to ponder on the same move the
  165.       // opponent has played. In case Signals.stopOnPonderhit is set we are
  166.       // waiting for 'ponderhit' to stop the search (for instance because we
  167.       // already ran out of time), otherwise we should continue searching but
  168.       // switching from pondering to normal search.
  169.       if (    token == "quit"
  170.           ||  token == "stop"
  171.           || (token == "ponderhit" && Search::Signals.stopOnPonderhit))
  172.       {
  173.           Search::Signals.stop = true;
  174.           Threads.main()->start_searching(true); // Could be sleeping
  175.       }
  176.       else if (token == "ponderhit")
  177.           Search::Limits.ponder = 0; // Switch to normal search
  178.  
  179.       else if (token == "uci")
  180.           sync_cout << "id name " << engine_info(true)
  181.                     << "\n"       << Options
  182.                     << "\nuciok"  << sync_endl;
  183.  
  184.       else if (token == "ucinewgame")
  185.       {
  186.           Search::clear();
  187.           Time.availableNodes = 0;
  188.       }
  189.       else if (token == "isready")    sync_cout << "readyok" << sync_endl;
  190.       else if (token == "go")         go(pos, is);
  191.       else if (token == "position")   position(pos, is);
  192.       else if (token == "setoption")  setoption(is);
  193.  
  194.       // Additional custom non-UCI commands, useful for debugging
  195.       else if (token == "flip")       pos.flip();
  196.       else if (token == "bench")      benchmark(pos, is);
  197.       else if (token == "d")          sync_cout << pos << sync_endl;
  198.       else if (token == "eval")       sync_cout << Eval::trace(pos) << sync_endl;
  199.       else if (token == "perft")
  200.       {
  201.           int depth;
  202.           stringstream ss;
  203.  
  204.           is >> depth;
  205.           ss << Options["Hash"]    << " "
  206.              << Options["Threads"] << " " << depth << " current perft";
  207.  
  208.           benchmark(pos, ss);
  209.       }
  210.       else
  211.           sync_cout << "Unknown command: " << cmd << sync_endl;
  212.  
  213.   } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
  214.  
  215.   Threads.main()->wait_for_search_finished();
  216. }
  217.  
  218.  
  219. /// UCI::value() converts a Value to a string suitable for use with the UCI
  220. /// protocol specification:
  221. ///
  222. /// cp <x>    The score from the engine's point of view in centipawns.
  223. /// mate <y>  Mate in y moves, not plies. If the engine is getting mated
  224. ///           use negative values for y.
  225.  
  226. string UCI::value(Value v) {
  227.  
  228.   stringstream ss;
  229.  
  230.   if (abs(v) < VALUE_MATE - MAX_PLY)
  231.       ss << "cp " << v * 100 / PawnValueEg;
  232.   else
  233.       ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
  234.  
  235.   return ss.str();
  236. }
  237.  
  238.  
  239. /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.)
  240.  
  241. std::string UCI::square(Square s) {
  242.   return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
  243. }
  244.  
  245.  
  246. /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
  247. /// The only special case is castling, where we print in the e1g1 notation in
  248. /// normal chess mode, and in e1h1 notation in chess960 mode. Internally all
  249. /// castling moves are always encoded as 'king captures rook'.
  250.  
  251. string UCI::move(Move m, bool chess960) {
  252.  
  253.   Square from = from_sq(m);
  254.   Square to = to_sq(m);
  255.  
  256.   if (m == MOVE_NONE)
  257.       return "(none)";
  258.  
  259.   if (m == MOVE_NULL)
  260.       return "0000";
  261.  
  262.   if (type_of(m) == CASTLING && !chess960)
  263.       to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
  264.  
  265.   string move = UCI::square(from) + UCI::square(to);
  266.  
  267.   if (type_of(m) == PROMOTION)
  268.       move += " pnbrqk"[promotion_type(m)];
  269.  
  270.   return move;
  271. }
  272.  
  273.  
  274. /// UCI::to_move() converts a string representing a move in coordinate notation
  275. /// (g1f3, a7a8q) to the corresponding legal Move, if any.
  276.  
  277. Move UCI::to_move(const Position& pos, string& str) {
  278.  
  279.   if (str.length() == 5) // Junior could send promotion piece in uppercase
  280.       str[4] = char(tolower(str[4]));
  281.  
  282.   for (const auto& m : MoveList<LEGAL>(pos))
  283.       if (str == UCI::move(m, pos.is_chess960()))
  284.           return m;
  285.  
  286.   return MOVE_NONE;
  287. }
  288.